1

I have a side navigation bar in my application which consists of 4 nav items. On initial load, they should look like below -

enter image description here

On click of each item, the background of that item should be changed as below -

enter image description here

I have tried below code (with limited knowledge on CSS) and was able to get what was shown in first image. For second image It displays like this and it should done as in second image.

HTML

<div class="container">
  <nav class="col-sm-3">
    <ul class="nav nav-pills nav-stacked">
      <li><a href="javascript:void(0);">Item 1</a></li>
      <li><a href="javascript:void(0);">Item 2</a></li>
      <li><a href="javascript:void(0);">Item 3</a></li>
      <li><a href="javascript:void(0);">Item 4</a></li>
   </ul>
  </nav>
</div>

CSS

.nav-pills>li {
   margin-left: -5px;
}
.nav-pills>li {
   width: 90%;
}
.nav-pills>li>a{
  color: #0D0D0D;
  background-color: #e1e1e1;
  padding: 15px;
}

.nav-pills>li>a:focus, .nav-pills>li>a:active{
  /*background-color: white;*/
  border:       30px solid lightgreen;
  border-left:  30px solid transparent;
  border-right: 0;
  width:        100%;

}

enter image description here

ChilBud
  • 185
  • 5
  • 26
  • 1
    Why is this tagged bootstrap-4 .. there is no longer a `nav-stacked` class? – Carol Skelly Jul 10 '18 at 20:53
  • @ZimSystem, Thanks and Removed bootstrap taggings.. I will check on nav-stacked class. I know about flex-column class to create vertical nav. What else can be used here ? – ChilBud Jul 10 '18 at 20:58
  • Potential duplicate of https://stackoverflow.com/questions/19241591/inside-transparent-arrow-on-the-left – DKyleo Jul 10 '18 at 21:16

3 Answers3

2
  • Create 2 layers using ::before and ::afterpseudo elements having same heights equal to 50% height of the parent element.
  • Apply background, border-radius and other necessary CSS properties on these layers.
  • Use skewX() transformation on hover to create the triangular effect.

Demo:

*, *::before, *::after { box-sizing: border-box; }

body {
  background: #333 url("https://k39.kn3.net/A01CCB6AE.jpg") no-repeat;
  background-size: cover;
  height: 100vh;
  padding: 10px;
  margin: 0;
}

.nav {
  font-family: Arial, sans-serif;
  list-style: none;
  padding: 0;
  margin: 0;
}

.nav li + li {
  margin-top: 3px;
}

.nav li a {
  text-decoration: none;
  border-radius: 2px;
  position: relative;
  padding: 12px 18px;
  overflow: hidden;
  display: block;
  color: #000;
}

.nav li a::before,
.nav li a::after {
  transition: transform .2s linear;
  transform-origin: left top;
  background-color: #dcdcdc;
  position: absolute;
  opacity: 0.5;
  content: '';
  height: 50%;
  z-index: -1;
  right: 0;
  left: 0;
  top: 0;
}

.nav li a::after {
  transform-origin: left bottom;
  top: auto;
  bottom: 0;
}


.nav li a:hover::before {
  transform: skewX(30deg);
}

.nav li a:hover::after {
  transform: skewX(-30deg);
}
<ul class="nav">
  <li><a href="#">Item 1</a></li>
  <li><a href="#">Item 2</a></li>
  <li><a href="#">Item 3</a></li>
  <li><a href="#">Item 4</a></li>
</ul>
Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95
1

I am posting my answer using bootstrap4 but the key point here is not relevant whether bootstrap3 or bootstrap4 is used. The key point here is how you can make a triangle.

Demo: http://jsfiddle.net/aq9Laaew/81019/

CSS Triangle

I am not going to explain here since it's already been explained well: https://css-tricks.com/snippets/css/css-triangle/

The idea here is to use :before of the active nav-link to make a triangle with white background.

Calculations

enter image description here

If you want the tip of the triangle right in the middle of the menu, you need to calculate its total height.

Total height = border top (1px) + 
               padding top (1rem) +
               line height (1.5 x 1rem = 1.5rem) +
               padding bottom (1rem) +
               border bottom (1px)

And then you divide it by 2 for the width of the border top and bottom.

Community
  • 1
  • 1
David Liang
  • 20,385
  • 6
  • 44
  • 70
  • Thank you. I have tried this approach and for some reason, my items are not stacked and are displayed as Item1 Item2 Item 3 and Item 4 overlapped. – ChilBud Jul 10 '18 at 22:03
  • As what I said in the beginning, I am using bootstrap4 and you're using bootstrap3. There are so many breaking changes between them. – David Liang Jul 10 '18 at 22:10
  • Ok, Got it. Will try to fix the issue and see the output. – ChilBud Jul 11 '18 at 02:40
1

Use box-shadow and Pseudo-elements

*{
  box-sizing:border-box
}
body {
   width: 100wh;
   height: 100vh; 
   background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
   background-size: 400% 400%; 
   animation: Gradient 15s ease infinite;
   }


   @keyframes Gradient {
  0%,100% { background-position: 0% 50% }
  50% { background-position: 100% 50% } 
} 
menu{
  margin: 40px auto;
  position: relative; 
  max-width: 320px
}
menu li{
  position: relative;
  list-style: none;
  overflow: hidden;  
  margin-bottom: 2px
}
menu li:before{
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    z-index:-1;
    height: 40px;
    width: 40px;
    opacity:0;
    margin-left: -30px;
    box-shadow: 0px 0px 0px 480px #d1e3ab;
    transform-origin: center;
    transform: rotate(45deg);
}
menu a{
  display: block;
  text-decoration: none;
  color:#5e5e5e;
  font-size: 14px;
  background-color: #e1e1e1;
  padding: 12px 10px;
  text-indent: 24px;
} 
menu li:hover a{ 
  background-color: transparent; 
}
menu li:hover:before{ 
  opacity:1
}
<menu>
  <li><a href="#">Item 1</a></li>
  <li><a href="#">Item 2</a></li>
  <li><a href="#">Item 3</a></li>
  <li><a href="#">Item 4</a></li>
</menu>
Gildas.Tambo
  • 22,173
  • 7
  • 50
  • 78
  • I wanted to change to ribbon based on click instead of hover, so changed to hover to focus and is not working.. – ChilBud Jul 24 '18 at 21:02
  • Why are trying to FOCUS list elements ? if you try to make a CLICK the you may consider using JAVASCRIPT click EVENT or change the structure to input & checkboxes. – Gildas.Tambo Jul 25 '18 at 05:47