CSS Directional Hover without using JavaScript

Prahalad S - Sep 28 - - Dev Community

CSS Directional Hover without using JavaScript

This is CSS hover effect from all directions like when you hover from left side of the element, the slide(hover effect) comes from left side. Same way to all other sides top, right, bottom. Its a directional hover effect from all four sides of element.

First lets create a CSS grid.

Create a parent div with id '#grid-plane'. Also Create another parent div inside 'grid-plane' with class name '.holder'. And lets create four child divs with class names .bottom, .left, .right, .top and add spans inside every element.

<div id="grid-plane">
  <div class="holder">
    <div class="bottom"><span></span></div>
    <div class="left"><span></span></div>
    <div class="right"><span></span></div>
    <div class="top"><span></span></div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, copy paste the parent div '.holder' to 15 times so that we get a grid system. (5x4 rows, columns).

<div id="grid-plane">
  <div class="holder">
    <div class="bottom"><span></span></div>
    <div class="left"><span></span></div>
    <div class="right"><span></span></div>
    <div class="top"><span></span></div>
  </div>
  <div class="holder">
    <div class="bottom"><span></span></div>
    <div class="left"><span></span></div>
    <div class="right"><span></span></div>
    <div class="top"><span></span></div>
  </div>
  <!-- here copied only 2 times. copy 15 times... -->
</div>
Enter fullscreen mode Exit fullscreen mode

Now, lets create CSS. '#grid-plane' and '.holder'.

body {
  font-family: "Lato", sans-serif;
  background: #7a7a7a;
}

/* grid-plane - 5x4 rows, columns */
#grid-plane {
  display: grid;
  width: 510px;
  grid-template-columns: repeat(auto-fit, minmax(20%, 1fr));
  margin: 100px auto;
}

.holder {
  width: 100px;
  height: 100px;
  position: relative;
  overflow: hidden;
  border: 1px solid white;
  background: #c7c7c7;
}
Enter fullscreen mode Exit fullscreen mode

Output:
Image description

Lets style the left, top, right, bottom divs.

.left,
.top,
.right,
.bottom {
  position: absolute;
  z-index: 1;
  cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

Assign width and height to spans with black background with opacity 0.7.

.left span,
.right span,
.top span,
.bottom span {
  position: absolute;
  width: 100px;
  height: 100px;
  background: black;
  opacity: 0.7;
  z-index: 10;
}
Enter fullscreen mode Exit fullscreen mode

Assign positions. We are moving spans out of '.holder' div initially. They overlay on 'holder' div when we hover on the 'holder' div in their directions.

.left, .left span {
  left: -50px;
  top: 0;
}

.right, .right span {
  left: 50px;
  top: 0;
}

.top, .top span {
  top: -50px;
  left: 0;
}

.bottom, .bottom span {
  top: 50px;
  left: 0;
}
Enter fullscreen mode Exit fullscreen mode

Lets create ':before' to left, top, right, bottom divs. Initially we are hiding them with opacity 0. This is a square box element and we are rotating it to 45deg and making it look like triangle. We are going to hover on these ':before' elements and we are faking it by hiding it to opacity 0 as if it doesn't exist.

.left:before,
.right:before,
.top:before,
.bottom:before {
  position: absolute;
  content: "";
  background: green;
  width: 71px;
  height: 71px;
  transform: rotate(45deg) translateX(29%);
  opacity: 0;
}
Enter fullscreen mode Exit fullscreen mode

This is the main part. Lets create hovers to left, top, right, bottom divs. Now this is very important. If we hover on 'holder' div from any one of the direction like:- If we hover from 'left' side then the span(the black background element with opacity 0.7) will slide from left side(animating) and cover the 'holder' div and also this below code ':before' element will be just behind the span element which is scaled to width and height to 215px and will translateX to -38% which covers the whole 'holder' div. This will block some hover conflicts from rest of the elements(.right, .top, .bottom) divs. These (.right, .top, .bottom) divs hover will not work properly because we have covered the entire 'holder' div with '.left:before' by scaling it to 215px. Same thing happens when we hover from right direction, avoids few conflicts from rest of the divs(.left, .top, .bottom). We can completely avoid all conflicts but we still need to code little more.

.left:hover:before,
.right:hover:before,
.top:hover:before,
.bottom:hover:before {
  width: 215px;
  height: 215px;
  transform: rotate(45deg) translateX(-38%);
}
Enter fullscreen mode Exit fullscreen mode

Remove all divs and keep only .left div inside '.holder' like below screenshot and comment overflow: hidden in '.holder' in CSS to view 'left:before' and span(black background) in browser.

<div id="grid-plane">
  <div class="holder">
    <div class="left"><span></span></div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Image description

This is how it looks if we have all 4 divs in 'holder' div and comment overflow: hidden in CSS.

<div id="grid-plane">
  <div class="holder">
    <div class="bottom"><span></span></div>
    <div class="left"><span></span></div>
    <div class="right"><span></span></div>
    <div class="top"><span></span></div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Image description

Now revert back, undo the above statements. (add all 'holder' parent divs back and uncomment overflow: hidden). Just like 15 times we added 'holder' parent divs earlier.

Lets create hover to the left, top, right bottom divs. Hover effect which covers(overlays) the 'holder' div with the spans(black background with opacity 0.7).

.bottom:hover span {
  top: -50px;
  animation: movefrombottom 0.25s;
}

.top:hover span {
  top: 50px;
  animation: movefromtop 0.25s;
}

.left:hover span {
  left: 50px;
  animation: movefromleft 0.25s;
}

.right:hover span {
  left: -50px;
  animation: movefromright 0.25s;
}
Enter fullscreen mode Exit fullscreen mode

Lets create animations to the spans of left, top, right, bottom divs.

@keyframes movefromtop {
  from { top: -50px; }

  to { top: 50px; }
}

@keyframes movefromleft {
  from { left: -50px; }

  to { left: 50px; }
}

@keyframes movefromright {
  from { left: 50px; }

  to { left: -50px; }
}
Enter fullscreen mode Exit fullscreen mode

Now we can avoid all hover conflicts by adding below codes.
Now lets hide other divs when we hover 'holder' div from any direction. Lets assume we are hovering from bottom direction. Then we have to hide below divs which are (.left, .right, .top divs). Just hiding all next element siblings.

Image description

.bottom:hover + *, .bottom:hover + * + *, .bottom:hover + * + * + * {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

If we hover from left direction. Through below code we are hiding rest of the divs. Hiding below two next element siblings and hiding first div(previousElement sibling) which is above the .left div using (has) class method.

Image description

.left:hover + *, .left:hover + * + *, .bottom:has(+ *:hover) {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

If we hover from right direction. Through below code we are hiding rest of the divs. Hiding below one next element sibling and hiding first two divs(.bottom, .left[previousElement siblings]) which is above the .right div using (has) class method.

Image description

.right:hover + *, .left:has(+ *:hover), .bottom:has(+ * + *:hover) {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

If we hover from top direction. Through below code we are hiding rest of the divs. Hiding above all previousElement siblings(.bottom, .left, .right) using (has) class method.

Image description

.right:has(+ *:hover), .left:has(+ * + *:hover),
.bottom:has(+ * + * + *:hover) {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

We are done with plane grid directional hovers.

Image description


Now lets create with images
Copy the <img-details> section 15 times like we did previously for plane grid.

<div id="grid-images">
  <div class="grid-wrapper">
    <div class="img-details">
      <div class="bottom"><span></span></div>
      <div class="left"><span></span></div>
      <div class="right"><span></span></div>
      <div class="top"><span></span></div>
      <div class="card">
        <img src="https://shorturl.at/NkOw6" alt="">
      </div>
      <h3>Click</h3>
    </div>
    <div class="img-details">
      <div class="bottom"><span></span></div>
      <div class="left"><span></span></div>
      <div class="right"><span></span></div>
      <div class="top"><span></span></div>
      <div class="card">
        <img src="https://shorturl.at/NkOw6" alt="">
      </div>
      <h3>Click</h3>
    </div>
    <!-- here copied only 2 times. copy 15 times... -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Just minifying the CSS to make it short here. Also do not delete all the previous CSS. Lets add few more here for images. Here we are just scaling the image and text on hover.

#grid-images {
  display: block; width: 500px; margin: 100px auto;
}

.grid-wrapper {
  display: grid; padding: 0; grid-gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(20%, 1fr));
  grid-auto-flow: dense; grid-auto-rows: auto;
  background: white; position: relative;
  overflow: hidden;
}

.img-details {
  display: flex; justify-content: center;
  align-items: center; position: relative;
  overflow: hidden; width: 100px;
  height: 100px; cursor: pointer;
}

.img-details .card {
  box-sizing: border-box; box-shadow: none;
  border: 0; border-radius: 0; z-index: 0;
  width: 100px; height: 100px;
}

.img-details .card > img {
  width: 100px; height: 100px;
  object-fit: cover; border-radius: 0;
  max-width: 100%; z-index: 0;
  position: relative; filter: brightness(0.5);
}

.img-details h3 {
  text-align: center; position: absolute;
  top: 50%; transform: scale(0.5) translateY(-50%);
  z-index: 0; opacity: 0; padding: 0;
  margin: 0; font-size: 12px; color: white;
  letter-spacing: 1px;
}

.img-details:hover h3 {
  pointer-events: none;
}

.img-details .card, .img-details .card > img,
.img-details h3 {
  transition: 0.25s ease;
}

.right:hover + * + * + * {
  opacity: 1; z-index: 1;
  transform: scale(1) translateY(-50%);
}

.right:hover + * + * img {
  transform: scale(1.15);
}

.left:hover + * + * + * + h3 {
  opacity: 1; z-index: 1;
  transform: scale(1) translateY(-50%);
  -webkit-transform: scale(1) translateY(-50%);
}

.left:hover + * + * + * img {
  transform: scale(1.15); -webkit-transform: scale(1.15);
}

.bottom:hover + * + * + * + * img {
  transform: scale(1.15); -webkit-transform: scale(1.15);
}

.bottom:hover + * + * + * + * + h3 {
  opacity: 1; z-index: 1;
  transform: scale(1) translateY(-50%);
  -webkit-transform: scale(1) translateY(-50%);
}

.top:hover + div + h3 {
  opacity: 1; z-index: 1;
  transform: scale(1) translateY(-50%);
  -webkit-transform: scale(1) translateY(-50%);
}

.top:hover + * img {
  transform: scale(1.15); -webkit-transform: scale(1.15);
}
Enter fullscreen mode Exit fullscreen mode

Now to give hyperlinks, assign to **<img-details>** div like in below code.

<div id="grid-images">
  <div class="grid-wrapper">
    <div class="img-details" onclick="location.href='https://www.google.com';"> <!-- hyperlink -->
      <div class="bottom"><span></span></div>
      <div class="left"><span></span></div>
      <div class="right"><span></span></div>
      <div class="top"><span></span></div>
      <div class="card">
        <img src="https://shorturl.at/NkOw6" alt="">
      </div>
      <h3>Click</h3>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Previously, we had span with black background with opacity 0.7 for hover. Check plain grid for output. Here I changed that span color to `background: #E91E63;` in CSS for hover effect for images.

Image description

Output for CSS Directional Hover for Images

Image description

Check here for running example : Click Here

Thank you for watching...

. . .
Terabox Video Player