skip to Main Content

I’ve created a simple HTML that includes an image with a 3px white border around it and text below the image. Here is the HTML: https://jsbin.com/rofisiwoya/edit?html,output

When you hover over the image, the border around it turns red (#ff4444). However, since this represents a video, I wanted the border around the image and the text to turn red at the same time no matter which element you’re hovering over, pretty much linking the hover effect for both elements.

So, I did that using javascript. On my computer, you can hover over either element and it will activate the hover effect for both. There’s not really a way you could de-synchronize them. However, the hover effect works much differently on touch devices since you can’t really hover over them, you can only click things or press down to hold. So, I added this javascript for touch devices:

`
const ZodiacThumbnail = document.getElementById(‘zodiac-thumbnail’);
const ZodiacTitle = document.getElementById(‘zodiac-title’);

    function applyActiveState() {
        ZodiacTitle.classList.add('active');
        ZodiacThumbnail.querySelector('a').classList.add('active');
    }

    function removeActiveState() {
        ZodiacTitle.classList.remove('active');
        ZodiacThumbnail.querySelector('a').classList.remove('active');
    }

    ZodiacThumbnail.addEventListener('mouseover', applyActiveState);
    ZodiacThumbnail.addEventListener('mouseout', removeActiveState);
    ZodiacTitle.addEventListener('mouseover', applyActiveState);
    ZodiacTitle.addEventListener('mouseout', removeActiveState);

    ZodiacThumbnail.addEventListener('touchstart', applyActiveState);
    ZodiacTitle.addEventListener('touchstart', applyActiveState);

    document.addEventListener('touchend', function(event) {
        if (!ZodiacThumbnail.contains(event.target) && !ZodiacTitle.contains(event.target)) {
            removeActiveState();
        }
    });
</script>`

This made it so that if you held down on either element, it would activate the hover effect for both elements. Like I mentioned though, hover works differently on touch devices, and I quickly figured out that you could de-synchronize these elements by simply doing this: https://streamable.com/wtlzzv

Now, realistically, do I think somebody is going to sit on their mobile phone messing around with my website? Well, no. But it annoys me quite a bit, and if there’s something I can add into my javascript that prevents this I would love to do so, even if it involves redoing the way that I "linked" the hover effect. If it was just the image and no text, there wouldn’t be anything to synchronize, but the fact that you can actually de-synchronize it with little to no effort isn’t exactly beautiful especially since a lot of people visiting my website will likely be using their mobile device.

2

Answers


  1. Why not use pointerenter and pointerleave events for both hover and touch interactions. These events handle both mouse and touch interactions more effectively and also you can make sure active state is consistently applied or removed by adding checks to see if the touch event is inside either of the elements

    <script>
        const ZodiacThumbnail = document.getElementById('zodiac-thumbnail');
        const ZodiacTitle = document.getElementById('zodiac-title');
    
        function applyActiveState() {
            ZodiacTitle.classList.add('active');
            ZodiacThumbnail.querySelector('a').classList.add('active');
        }
    
        function removeActiveState() {
            ZodiacTitle.classList.remove('active');
            ZodiacThumbnail.querySelector('a').classList.remove('active');
        }
    
        ZodiacThumbnail.addEventListener('pointerenter', applyActiveState);
        ZodiacThumbnail.addEventListener('pointerleave', removeActiveState);
        ZodiacTitle.addEventListener('pointerenter', applyActiveState);
        ZodiacTitle.addEventListener('pointerleave', removeActiveState);
    
        ZodiacThumbnail.addEventListener('touchstart', applyActiveState);
        ZodiacTitle.addEventListener('touchstart', applyActiveState);
    
        document.addEventListener('touchend', function(event) {
            if (!ZodiacThumbnail.contains(event.target) && !ZodiacTitle.contains(event.target)) {
            removeActiveState();
            }
        });
    </script>
    
    Login or Signup to reply.
  2. Use :has() pseudo-class:

    body {
      background-color: #111111;
      color: #eeeeee;
      font-family: 'DIN-2014', sans-serif;
      text-align: center;
      padding: 20px;
    }
    
    div {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    a {
      text-decoration: none;
      font-size: 17px;
      letter-spacing: 0.5px;
      color: #eeeeee;
      transition:
        border-color 0.25s,
        color 0.25s;
    }
    
    a:hover {
      border-color: #ff4444;
      color: #ff4444;
    }
    
    .video {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-top: 25px;
    }
    
    .video .thumbnail {
      display: flex;
      justify-content: center;
    }
    
    .video .thumbnail a {
      display: block;
      padding: 0;
      border: 3px solid #eeeeee;
      width: 865px;
      margin-bottom: 0px;
      transition: border-color 0.25s;
    }
    
    .video .thumbnail img {
      display: block;
      width: 100%;
      height: 100%;
      border-radius: 0;
    }
    
    .video .title {
      font-size: 22px;
      padding: 0;
      border: 0;
      width: 371px;
      margin-top: 10px;
      transition: color 0.25s;
    }
    
    /* Responsive Design */
    @media only screen and (max-width: 600px) {
      div a {
        width: 85%;
        height: 85%;
      }
      .video .thumbnail a {
        width: 105%;
      }
      .video .title {
        font-size: 17px;
        width: 85%;
      }
    }
    
    /* add */
    
    .thumbnail,
    .video .thumbnail a {
      max-width: 100%;
    }
    
    .video:has(.thumbnail:hover),
    .video:has(.title:hover) {
      .title {
        color: #ff4444;
      }
      .thumbnail a {
        border-color: #ff4444;
        color: #ff4444;
      }
    }
    <div class="video">
      <div
        class="thumbnail"
        id="zodiac-thumbnail"
      >
        <a href="https://www.placeholder.com">
          <img src="https://www.ghoulangel.com/images/thumbnails/zodiac.png" />
        </a>
      </div>
      <a
        href="https://www.placeholder.com"
        class="title"
        id="zodiac-title"
        >THE SEARCH FOR THE ZODIAC KILLER</a
      >
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search