title: Why does toggling an anchor's child element with display cause a double tap, while toggling with opacity does not?
body: <p>Why does toggling <code>display</code> and <code>opacity</code> on an anchor's child elements affect touch events differently on iOS devices?</p>
  
  <p>I have a navigation menu in which each item contains an image and a short string of text.</p>
  
  <ul>
  <li><p>Each image has a <code>:hover</code> state that uses the same shared overlay image.</p></li>
  <li><p>If the <code>:hover</code> pseudo class sets the overlay image's <code>display</code> value, users on iOS devices have to tap the link twice.</p></li>
  <li><p>If the <code>:hover</code> pseudo class sets the overlay image's <code>opacity</code> value, users on iOS devices <strong>do not</strong> have to tap the link twice.</p></li>
  <li><p>In both cases, it doesn't matter if the overlay image covers the entire base image or is a smaller inset overlay.</p></li>
  <li><p>In both cases, including the <code>:active</code> and <code>:focus</code> pseudo classes does not change the behavior.</p></li>
  </ul>
  
  <p>I know that I can just remove the <code>:hover</code> rules with JavaScript for touch devices. I'm wondering if anyone knows the <strong>why</strong> there is a difference between <code>display</code> and <code>opacity</code>. </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>a {
    display: inline-block;
    height: 200px;
    position: relative;
    width: 150px;
  }
  
  a img.overlay {
    display: block;
    left: 0;
    position: absolute;
    top: 0;
  }
  
  a.overlay-display img.overlay {
    display: none;
  }
  
  a.overlay-display:hover img.overlay {
    display: block;
  }
  
  a.overlay-opacity img.overlay {
    opacity: 0;
  }
      
  a.overlay-opacity:hover img.overlay {
    opacity: 1;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;p&gt;
    Set overlay display:
  &lt;/p&gt;
  
  &lt;a class="overlay-display overlay-display-first" href="http://www.google.com" target="_blank"&gt;
    &lt;img class="overlay" src="http://placehold.it/150x150/ff0000"&gt;
    &lt;img src="http://placehold.it/150x150"&gt; link text
  &lt;/a&gt;
  
  &lt;a class="overlay-display overlay-display-last" href="http://www.google.com" target="_blank"&gt;
    &lt;img src="http://placehold.it/150x150"&gt;
    &lt;img class="overlay" src="http://placehold.it/150x150/ff0000"&gt; link text
  &lt;/a&gt;
  
  &lt;a class="overlay-display overlay-display-first" href="http://www.google.com" target="_blank"&gt;
    &lt;img class="overlay" src="http://placehold.it/50x50/ff0000"&gt;
    &lt;img src="http://placehold.it/150x150"&gt; link text
  &lt;/a&gt;
  
  &lt;a class="overlay-display overlay-display-last" href="http://www.google.com" target="_blank"&gt;
    &lt;img src="http://placehold.it/150x150"&gt;
    &lt;img class="overlay" src="http://placehold.it/50x50/ff0000"&gt; link text
  &lt;/a&gt;
  
  &lt;p&gt;
    Set overlay opacity:
  &lt;/p&gt;
  
  &lt;a class="overlay-opacity overlay-opacity-first" href="http://www.google.com" target="_blank"&gt;
    &lt;img class="overlay" src="http://placehold.it/150x150/ff0000"&gt;
    &lt;img src="http://placehold.it/150x150"&gt; link text
  &lt;/a&gt;
  
  &lt;a class="overlay-opacity overlay-opacity-last" href="http://www.google.com" target="_blank"&gt;
    &lt;img src="http://placehold.it/150x150"&gt;
    &lt;img class="overlay" src="http://placehold.it/150x150/ff0000"&gt; link text
  &lt;/a&gt;
  
  &lt;a class="overlay-opacity overlay-opacity-first" href="http://www.google.com" target="_blank"&gt;
    &lt;img class="overlay" src="http://placehold.it/50x50/ff0000"&gt;
    &lt;img src="http://placehold.it/150x150"&gt; link text
  &lt;/a&gt;
  
  &lt;a class="overlay-opacity overlay-opacity-last" href="http://www.google.com" target="_blank"&gt;
    &lt;img src="http://placehold.it/150x150"&gt;
    &lt;img class="overlay" src="http://placehold.it/50x50/ff0000"&gt; link text
  &lt;/a&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Additionally, it doesn't seem to matter if I'm toggling an inline element or a block element. In this snippet, I'm toggling a <code>span</code> inside the anchor.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>a {
    display: inline-block;
    height: 200px;
    position: relative;
    width: 150px;
  }
  
  a.text-display span.overlay {
    display: none;
  }
  
  a.text-display:hover span.overlay {
    display: inline;
  }
  
  a.text-opacity span.overlay {
    opacity: 0;
  }
  
  a.text-opacity:hover span.overlay {
    opacity: 1;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;p&gt;
    Set text display:
  &lt;/p&gt;
  
  &lt;a class="text-display text-display-last" href="http://www.google.com" target="_blank"&gt;
    &lt;img src="http://placehold.it/150x150"&gt; link text
    &lt;span class="overlay"&gt;some other text&lt;/span&gt;
  &lt;/a&gt;
  
  &lt;p&gt;
    Set text opacity:
  &lt;/p&gt;
  
  &lt;a class="text-opacity text-opacity-last" href="http://www.google.com" target="_blank"&gt;
    &lt;img src="http://placehold.it/150x150"&gt; link text
    &lt;span class="overlay"&gt;some other text&lt;/span&gt;
  &lt;/a&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>According to the iOS Developer Library documentation for <a href="https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW4" rel="nofollow noreferrer">One-Finger Events</a>:</p>
  
  <blockquote>
    <p>Mouse events are delivered in the same order you'd expect in other web
    browsers illustrated in Figure 6-4. If the user taps a nonclickable
    element, no events are generated. If the user taps a clickable
    element, events arrive in this order: mouseover, mousemove, mousedown,
    mouseup, and click. The mouseout event occurs only if the user taps on
    another clickable item. Also, if the contents of the page changes on
    the mousemove event, no subsequent events in the sequence are sent.
    This behavior allows the user to tap in the new content.</p>
  </blockquote>
  
  <p><a href="https://i.stack.imgur.com/gLTEt.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gLTEt.jpg" alt="Figure 6-4  One-finger gesture emulating a mouse"></a></p>
  
  <p>The problem is that it's not clear what constitutes a <strong>content change</strong>.</p>