Dan Dan - 3 months ago 13
CSS Question

Remove fluctuations in height of the ul whilst under a css transition

The following code is used to define the style of a side navigation which I use. And it works great without any transitions.

SCSS Code and working JSFiddle

.side-nav{
position: fixed;
z-index: 100;
right: 0;
margin-top: 15vh;

ul {
list-style: none;
background: red;
border-style: solid;
border-right-style: none;
border-width: 3px;
border-color: blue;
@include border-radius(20px, 0, 20px, 0);
width: 1cm !important;
}

li {
position: relative;
display: block;
right: 0;
width: 1cm;

span {
white-space: pre;

&.short {
color: black;
display: block;
}

&.long {
display: none;
color: white;
}
}

&:hover {
right:200%;
width: 3cm;
@include border-radius(20px, 0, 20px, 0);
border-style: solid;
border-right-style: none;
border-width: 3px;
border-color: blue;
background: red;
margin: -3px 0;

span {
&.short {
display: none;
}

&.long {
display: block;
}
}
}
}

a {
position: relative;
display: block;
text-decoration: none;

padding: 10px 0;
text-align: center;
}
}


However, when you add the transition code, as you will see if you go on the JSFiddle, the height of the
ul
fluctuates.

SCSS Code and JSFiddle which demonstrates problem

.side-nav{
position: fixed;
z-index: 100;
right: 0;
margin-top: 15vh;

ul {
list-style: none;
background: red;
border-style: solid;
border-right-style: none;
border-width: 3px;
border-color: blue;
@include border-radius(20px, 0, 20px, 0);
width: 1cm !important;
}

li {
position: relative;
display: block;
right: 0;
width: 1cm;
@include transition(all 1s);

span {
white-space: pre;

&.short {
color: black;
display: block;
}

&.long {
display: none;
color: white;
}
}

&:hover {
@include transition(all 1s);
right:200%;
width: 3cm;
@include border-radius(20px, 0, 20px, 0);
border-style: solid;
border-right-style: none;
border-width: 3px;
border-color: blue;
background: red;
margin: -3px 0;

span {
&.short {
display: none;
}

&.long {
display: block;
}
}
}
}

a {
position: relative;
display: block;
text-decoration: none;

padding: 10px 0;
text-align: center;
}
}


This is caused when I account for the border and try to keep everything in line without changing the height. To make the border of the top and bottom
li
elements blend in with the border of the
ul
, I used the line of code
margin: -3px 0
. This is because the border width is
3px
.

My question is how do I make it so that the easing of the margin and border is even so the height of the
ul
remains stationary throughout the transition?

Answer

You're adding the border on hover which changes the height of the li.

Instead, give it a default transparent border and just change the border color on hover.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.side-nav {
  position: fixed;
  z-index: 100;
  right: 0;
  margin-top: 1vh;
}
.side-nav ul {
  list-style: none;
  background: red;
  border-style: solid;
  border-right-style: none;
  border-width: 3px;
  border-color: blue;
  -moz-border-top-left-radius: 20px;
  border-top-left-radius: 20px;
  -moz-border-top-right-radius: 0;
  border-top-right-radius: 0;
  -moz-border-bottom-left-radius: 20px;
  border-bottom-left-radius: 20px;
  -moz-border-bottom-right-radius: 0;
  border-bottom-right-radius: 0;
  width: 1cm !important;
}
.side-nav li {
  position: relative;
  display: block;
  right: 0;
  width: 1cm;
  border: 3px solid transparent;
  -webkit-transition: all 1s;
  transition: all 1s;
}
.side-nav li span {
  white-space: pre;
}
.side-nav li span.short {
  color: black;
  display: block;
}
.side-nav li span.long {
  display: none;
  color: white;
}
.side-nav li:hover {
  -webkit-transition: all 1s;
  transition: all 1s;
  right: 200%;
  width: 3cm;
  -moz-border-top-left-radius: 20px;
  border-top-left-radius: 20px;
  -moz-border-top-right-radius: 0;
  border-top-right-radius: 0;
  -moz-border-bottom-left-radius: 20px;
  border-bottom-left-radius: 20px;
  -moz-border-bottom-right-radius: 0;
  border-bottom-right-radius: 0;
  border-color: blue;
  background: red;
}
.side-nav li:hover span.short {
  display: none;
}
.side-nav li:hover span.long {
  display: block;
}
.side-nav a {
  position: relative;
  display: block;
  text-decoration: none;
  padding: 10px 0;
  text-align: center;
}
<nav id="side-nav" class="side-nav" role="navigation">
  <ul>
    <li><a href="#"><span class="short">S</span><span class="long">Long</span></a>
    </li>
    <li><a href="#"><span class="short">S</span><span class="long">Long</span></a>
    </li>
    <li><a href="#"><span class="short">S</span><span class="long">Long</span></a>
    </li>
    <li><a href="#"><span class="short">S</span><span class="long">Long</span></a>
    </li>
    <li><a href="#"><span class="short">S</span><span class="long">Long</span></a>
    </li>
  </ul>
</nav>

JSfiddle Demo