Search code examples
javascriptecmascript-6viewportblurintersection-observer

Remove keyboard focus from a form element after it goes out of viewport


How can I use the relatively new Intersection Observer API to detect when input that’s currently focused goes outside the viewport, so that when it does, the focus on that input is removed?

The solution should work in Safari for iOS.


Here is my code so far:

document.addEventListener("DOMContentLoaded", _ => {
  const focusedInput = document.activeElement
  
  // ?
  focusedInput.blur()
})
html { height: 100% }

html, body, main, section {
  display: flex;
  flex-grow: 1
}

main { flex-direction: column }

section {
  justify-content: center;
  align-items: center;
  flex: 1 0 100%
}
<main>
  <section>
    <form action=submit method=post>
      <fieldset>
        <legend>Enter Your Details</legend>
        <label>Email<br><input type=email name=email placeholder=jane@example.com></label><hr>
        <label>Message<br><textarea name=briefing placeholder="Lorem ipsum dolor sit amet."></textarea></label><hr>
        <input type=submit value=Submit>
      </fieldset>
    </form>
  </section>
  <section>
    <h2>Second Page</h2>
  </section>
</main>


Solution

  • In doc you linked there is a fiddle Why don't you use it?

    Just modify it to something like..

    document.addEventListener("DOMContentLoaded", _ => {
        let observerOptions = {
            root: null,
            rootMargin: "0px",
            threshold: [0, 0.1, 0.99]
        };
    
        let intersectionCallback = (entries) => {
          entries.forEach((entry) => {
            if (entry.intersectionRatio == 0) { // fully invisible
              //document.activeElement.blur()
            }
            if (entry.intersectionRatio < 1) { // partially invisible
              document.activeElement.blur()
            }
          });
        }
        
        let observer = new IntersectionObserver(intersectionCallback, observerOptions);
        observer.observe(document.querySelector("#myForm"));
      
    })
    html { height: 100% }
    
    html, body, main, section {
      display: flex;
      flex-grow: 1
    }
    
    main { flex-direction: column }
    
    section {
      justify-content: center;
      align-items: center;
      flex: 1 0 100%
    }
    <main>
      <section>
        <form action=submit method=post id=myForm>
          <fieldset>
            <legend>Enter Your Details</legend>
            <label>Email<br><input type=email name=email placeholder=jane@example.com></label><hr>
            <label>Message<br><textarea name=briefing placeholder="Lorem ipsum dolor sit amet."></textarea></label><hr>
            <input type=submit value=Submit>
          </fieldset>
        </form>
      </section>
      <section>
        <h2>Second Page</h2>
      </section>
    </main>