skip to Main Content

After opening the HTMLDialogElement the first click inside of it also focuses the dialog element on Chromium. Basically each first click within the dialog fires the focus event.
Thant is not the case on Firefox.

In my current use case, the focus trap causes problems for me but everything is fine on FF.

Is this an intentional behavior of Chromium?
Why is there a difference?

CHROMIUM BEHAVIOR:

  • step 1: press show()
  • step 2: click within dialog -> focus event fired
  • step 3: click outside dialog and click within dialog again -> focus event fired
  • setp 4: close()
  • step 5: showModal()
  • step 6: click anywhere -> focus event fired

FIREFOX BEHAVIOR:

    • no focus events fired ever

Stackblitz:

https://stackblitz.com/edit/typescript-s7ajm9?file=index.html,index.ts

I will create a workaround for my current use case and post it here as a solution but the question is if there is a reason to have a different behavior?

2

Answers


  1. Chosen as BEST ANSWER

    Working solution for my use case:

    let lastFocusedElement;
    
    const dialog = document.querySelector('dialog');
    const button1 = document.querySelector('#button1');
    const button2 = document.querySelector('#button2');
    const span = document.querySelector('span');
    
    const handleDialogFocus = (event) => {
      if (lastFocusedElement) {
        if (event.target === dialog) {
          event.preventDefault();
        }
        lastFocusedElement.focus();
        lastFocusedElement = undefined;
      }
    }
    
    
    const handleDialogClick = (e) => {
      if (!dialog) {
        return;
      }
    
      const target = e.target;
    
      if (target && (target !== dialog)) {
        lastFocusedElement = target;
      }
    
    }
    
    const handleButtonClick = () => {
      dialog.showModal();
    }
    
    
    const handleButton2Click = () => {
      dialog.close();
      button1.focus();
    }
    
    dialog.addEventListener('focus', handleDialogFocus);
    dialog.addEventListener('click', handleDialogClick);
    button1.addEventListener('click', handleButtonClick);
    button2.addEventListener('click', handleButton2Click);
    button:focus {
      border: 2px solid red;
    }
    <dialog>
      This is an open modal
      <button id="button2">Close and focus back to button</button>
    </dialog>
    <button id="button1">open modal</button>


  2. The difference in behavior between Chromium and Firefox is likely due to the way each browser’s implementation of the HTMLDialogElement specification handles focus. Firefox may not be firing a focus event on the first click within the dialog because it doesn’t consider this interaction in focus. However, Chromium does and fires a focus event.

    For this, you could try to add a condition in your focus event listener to check if the event target is the dialog itself. If it is, you can prevent the default behavior.

    Example;

    dialog.addEventListener('focus', (event) => {
     if (event.target === dialog) {
       event.preventDefault();
     } else {
       console.warn('The dialog > focus');
     }
    });
    

    *Note that browser behavior can vary, and it’s always a good idea to test your code in multiple browsers to ensure it behaves as expected.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search