skip to Main Content

I Would like to do a simple custom menu with 5 fields.
On mouseover the field under the mouse should expand ist width.
Therefore the other fields must shrink in width.

So far so good but the problem is, that the transition function is not really linear and the total width of the menu changes uncontrolled when the mouse changes fast over the menufields.

Does anybody know a more elegant but first of all a more functional solution for that problem?

My code so far is as follows:

function kr_menue(id) {
  document.getElementById('id-m1').style.width = "17%";
  document.getElementById('id-m2').style.width = "17%";
  document.getElementById('id-m3').style.width = "17%";
  document.getElementById('id-m4').style.width = "17%";
  document.getElementById('id-m5').style.width = "17%";
  document.getElementById(id).style.width = "32%";
  return true;
}

function kr_menue0(id) {
  document.getElementById('id-m1').style.width = "20%";
  document.getElementById('id-m2').style.width = "20%";
  document.getElementById('id-m3').style.width = "20%";
  document.getElementById('id-m4').style.width = "20%";
  document.getElementById('id-m5').style.width = "20%";
  return true;
}
.menue0 {
  float: left;
  border: 1px solid white;
  margin: 0px;
  height: 300px;
  background-color: grey;
  justify-content: center;
  transition: width 1s linear;
}

.menue0:hover {
  cursor: pointer;
}

#id-m1 {
  width: 20%;
}

#id-m2 {
  width: 20%;
}

#id-m3 {
  width: 20%;
}

#id-m4 {
  width: 20%;
}

#id-m5 {
  width: 20%;
}
<div onmouseout="kr_menue0()">
  <div class="menue0" id="id-m1" onmouseover="kr_menue('id-m1')"> Menue 1</div>
  <div class="menue0" id="id-m2" onmouseover="kr_menue('id-m2')"> Menue 2</div>
  <div class="menue0" id="id-m3" onmouseover="kr_menue('id-m3')"> Menue 3</div>
  <div class="menue0" id="id-m4" onmouseover="kr_menue('id-m4')"> Menue 4</div>
  <div class="menue0" id="id-m5" onmouseover="kr_menue('id-m5')"> Menue 5</div>
</div>

/* RESULT ****************** */
https://kristallvelo.ch/test-seite/

3

Answers


  1. In my experience transition-timing-function:ease-in-out works best in such cases. Also I restructured your code to use flexbox.

    .menu {
      width: 100%;
      display: flex;
      flex-direction: row;
    }
    .menu-item {
      height: 50px;
      flex-grow: 1.5;
      background-color: gray;
      border: 1px solid white;
      transition:flex-grow 1s ease-in-out;
    }
    .menu-item:hover {
      flex-grow: 2;
    }
    <div class="menu">
      <div class="menu-item"> Menu 1</div>
      <div class="menu-item"> Menu 2</div>
      <div class="menu-item"> Menu 3</div>
      <div class="menu-item"> Menu 4</div>
      <div class="menu-item"> Menu 5</div>
    </div>
    Login or Signup to reply.
  2. As dantheman pointed out, javascript is not required here. There are a lot of ways of doing this, but here’s one.

    Get rid of javascript and do everything in CSS. Modify your CSS as follows, but make sure you wrap your divs in a wrapper element. I just used another div.

    Basically you’re using flex properties to manage the element widths. You’re telling the wrapper to be flexible, add space between each element to fit the container (in this case .menues), and each .menue0 element is the thing that stretches/contracts. You can modify each flex-basis percentage to whatever you like.

    .menues {
      display: flex;
      justify-content: space-between;
    }
    
    .menue0 {
      flex-basis: 20%;
      border:1px solid white; 
      height:300px; 
      background-color:grey; 
      cursor:pointer;
      transition: all 0.5s;
    }
    
    .menue0:hover {
      flex-basis: 32%;
    }
    <div class="menues">
      <div class="menue0">Menu 1</div>
      <div class="menue0">Menu 2</div>
      <div class="menue0">Menu 3</div>
      <div class="menue0">Menu 4</div>
      <div class="menue0">Menu 5</div>
    </div>
    Login or Signup to reply.
  3. If you make your container flex, you can make use of css hover to achieve what you want, instead of using js:

    .menu {
      display: flex;                  /* make parent flex */
    }
    
    .menue0 {
      display: flex;
      box-sizing: border-box;        /* add this so border is part of your width */
      width: 20%; 
      border: 1px solid white;
      margin: 0px;
      height: 300px;
      background-color: grey;
      justify-content: center;
      transition: width 1s linear;
      flex-grow:1;                   /* add this so that all columns always take up full width of parent */
    }
    
    .menu:hover .menue0 {
      width: 17%;                    /* change children to 17% when parent is hovered */
    }
    
    .menu .menue0:hover {
      width: 32%;                    /* change hovered child to 32% */
    }
    <div class="menu">
      <div class="menue0" id="id-m1"> Menue 1</div>
      <div class="menue0" id="id-m2"> Menue 2</div>
      <div class="menue0" id="id-m3"> Menue 3</div>
      <div class="menue0" id="id-m4"> Menue 4</div>
      <div class="menue0" id="id-m5"> Menue 5</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search