Minimal Hover Menu - The Right Way

2

In the example below we have an interesting menu, with a effect hover, which follows the mouse and its items. Everything is very beautiful and works well. The problem is that this menu is set to default dimensions, so you can not add more items or resize by keeping effect .

What I would like is to have this same effect in a traditional, fluid, flexible, no-dimensioned menu without nth-child

@import url(https://fonts.googleapis.com/css?family=Roboto:100);
 
body {
  font-family:'HelveticaNeue-UltraLight', 'Helvetica Neue UltraLight', Roboto, Arial, Sans-serif;
  background:#ecf0f1;
}
 
nav {
  width:400px;
  height:60px;
  margin:125px auto 0;
  text-align:center;
  background:#fff;
  box-shadow:0 1px 2px #ddd;
  backface-visibility:hidden;
}
 
nav ul {
  position:relative;
}
 
nav ul li {
  display:inline-block;
  line-height:60px;
  width:100px;
  margin-right:-4px;
}
 
nav ul li:first-child {
  margin-left:-4px;
}
 
li:nth-child(4):after {
  content:"";
  width:100px;
  height:3px;
  position:absolute;
  background:#3498db;
  top:0;
  left:0;
  transform:translateX(0);
  transition:.5s;
}
 
nav ul li:nth-child(2):hover ~ li:nth-child(4):after { transform:translateX(100px); }
nav ul li:nth-child(3):hover ~ li:nth-child(4):after { transform:translateX(200px); }
nav ul li:nth-child(4):hover:after { transform:translateX(300px); }
 
nav ul li a {
  text-decoration:none;
  color:#2c3e50;
  cursor:pointer;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<nav>
  <ul>
    <li><a>Home</a></li>
    <li><a>About</a></li>
    <li><a>Clients</a></li>
    <li><a>Work</a></li>
  </ul>
</nav>

Sample menu where I would like the effect of the above example to be applied.

.dropdownmenu ul, .dropdownmenu li {
	margin: 0;
	padding: 0;
}
.dropdownmenu ul {
	background: gray;
	list-style: none;
	width: 100%;
}
.dropdownmenu li {
	float: left;
	position: relative;
	width:auto;
}
.dropdownmenu a {
	background: #30A6E6;
	color: #FFFFFF;
	display: block;
	font: bold 12px/20px sans-serif;
	padding: 10px 25px;
	text-align: center;
	text-decoration: none;
	-webkit-transition: all .25s ease;
	-moz-transition: all .25s ease;
	-ms-transition: all .25s ease;
	-o-transition: all .25s ease;
	transition: all .25s ease;
}
.dropdownmenu li:hover a {
	background: #000000;
}
#submenu {
	left: 0;
	opacity: 0;
	position: absolute;
	top: 35px;
	visibility: hidden;
	z-index: 1;
}
li:hover ul#submenu {
	opacity: 1;
	top: 40px;	/* adjust this as per top nav padding top & bottom comes */
	visibility: visible;
}
#submenu li {
	float: none;
	width: 100%;
}
#submenu a:hover {
	background: #DF4B05;
}
#submenu a {
	background-color:#000000;
}
<nav class="dropdownmenu">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About Me</a></li>
    <li><a href="#">Articles on HTML5 & CSS3</a>
      <ul id="submenu">
        <li><a href="#">Difference between SVG vs. Canvas</a></li>
        <li><a href="#">New features in HTML5</a></li>
        <li><a href="#">Creating links to sections within a webpage</a></li>
      </ul>
    </li>
    <li><a href="#">News</a></li>
    <li><a href="#">Contact Us</a></li>
  </ul>
</nav>

Source 1: link

Source 2: link

    
asked by anonymous 16.03.2018 / 19:39

2 answers

2

You can use JavaScript to have the same effect. I made a modification in this class below by adding position: relative :

.dropdownmenu ul {
    background: gray;
    list-style: none;
    width: 100%;
    position: relative;
}

And I created a class that will be the "barrinha" that accompanies the mouse. The bar will initially be placed in li with class .current-link :

.barra {
  height:3px;
  position:absolute;
  background: #00F71C;
  transition:.5s;
  z-index: 9;
}

What I did was create the bar dynamically, positioned in the first <li> . When the mouse passes the other% s of% s, the bar changes position and width, taking advantage of the li effect.

See:

document.addEventListener("DOMContentLoaded", function(){

   function barPos(bar, act){
      var pos = "left:"
      +act.offsetLeft
      +"px;"
      +"width:"
      +act.clientWidth
      +"px;"
      +"top:"
      +act.offsetTop
      +"px;";
      
      bar.style.cssText = pos;
   }
   
   var lis = document.body.querySelectorAll(".dropdownmenu > ul > li"),
       act = document.body.querySelector(".dropdownmenu > ul li.current-link"),
       bar = document.createElement("span"),
       cur = Array.prototype.indexOf.call(lis, act);
       
   bar.className = "barra";
   lis[0].appendChild(bar);
   var bar = document.body.querySelector(".barra");
   
   barPos(bar, act);
   
   for(x=0; x<lis.length; x++){
      lis[x].addEventListener("mouseover", function(){
         var idx = Array.prototype.indexOf.call(lis, this);
         if(cur != idx){
            cur = idx;
            bar.style.cssText = "left:"
            +this.offsetLeft
            +"px;"
            +"top:"
            +this.offsetTop
            +"px;"
            +"width:"
            +this.clientWidth
            +"px;";
         }
      });

      lis[x].addEventListener("mouseleave", function(){
         cur = Array.prototype.indexOf.call(lis, act);
         barPos(bar, act);
      });
   }
   
   window.addEventListener("resize", function(){ barPos(bar, act); });
   
});
.dropdownmenu ul, .dropdownmenu li {
	margin: 0;
	padding: 0;
}
.dropdownmenu ul {
	background: gray;
	list-style: none;
	width: 100%;
   position: relative;
}
.dropdownmenu li {
	float: left;
	position: relative;
	width:auto;
}
.dropdownmenu a {
	background: #30A6E6;
	color: #FFFFFF;
	display: block;
	font: bold 12px/20px sans-serif;
	padding: 10px 25px;
	text-align: center;
	text-decoration: none;
	-webkit-transition: all .25s ease;
	-moz-transition: all .25s ease;
	-ms-transition: all .25s ease;
	-o-transition: all .25s ease;
	transition: all .25s ease;
}
.dropdownmenu li:hover a {
	background: #000000;
}
#submenu {
	left: 0;
	opacity: 0;
	position: absolute;
	top: 35px;
	visibility: hidden;
	z-index: 1;
}
li:hover ul#submenu {
	opacity: 1;
	top: 40px;	/* adjust this as per top nav padding top & bottom comes */
	visibility: visible;
}
#submenu li {
	float: none;
	width: 100%;
}
#submenu a:hover {
	background: #DF4B05;
}
#submenu a {
	background-color:#000000;
}

.barra {
  height:3px;
  position:absolute;
  background: #00F71C;
  transition:.5s;
  z-index: 9;
}
<nav class="dropdownmenu">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About Me</a></li>
    <li><a href="#">Articles on HTML5 & CSS3</a>
      <ul id="submenu">
        <li><a href="#">Difference between SVG vs. Canvas</a></li>
        <li><a href="#">New features in HTML5</a></li>
        <li><a href="#">Creating links to sections within a webpage</a></li>
      </ul>
    </li>
    <li><a href="#">News</a></li>
    <li class="current-link"><a href="#">Contact Us</a></li>
  </ul>
</nav>
    
16.03.2018 / 22:08
1

John following all the rules that you spoke I managed to get to that result.

The example uses FlexBox so it is very responsive. You can add as many items as you want that will fit right (Maybe you'll have to narrow the font down a bit if you have more items ...) But no longer works fine on smaller screens up to a point. p>

html, body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}
body {
    background-image: url(http://placecage.com/800/600);
    background-size: cover;
    background-repeat: no-repeat;
}
.navbar {
    width: 100%;
    height: 50px;
    padding: 0;
    text-align: center;
    background-color: rgba(0,0,0,.5);
    display: flex;
    align-items: center;
    position: relative;
    top: 0;
}
.box {
    flex: 1;
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
}

.box::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    height: 0.5rem;
    width: 100%;
    background-color: #0f0;
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 350ms;
}
.box:hover::after {
    background-color: #0f0;
    transform: scaleX(1);
    transform-origin: left;
}

.link {
    color: #fff;
    text-transform: uppercase;
    font-size: 1.25rem;
    text-decoration: none;
    font-family: sans-serif;
}
<nav class="navbar">
    <div class="box">
        <a class="link" href="">item 1</a>
    </div>
    <div class="box">
        <a class="link" href="">item 2</a>
    </div>
    <div class="box">
        <a class="link" href="">item 3</a>
    </div>
    <div class="box">
        <a class="link" href="">item 4</a>
    </div>
    <div class="box">
        <a class="link" href="">item 5</a>
    </div>
</nav>

OBS: The only detail is that the animation does not always follow the mouse. But if you want you can make it start at the "center" of .Box , just put transform-origin: center; to see how it works.

    
16.03.2018 / 20:56