Brenden Kehren
Brenden Kehren

Reputation: 6117

Triangle within a triangle CSS

I'm looking to create the following setup for a navigation structure.

enter image description here

I'm able to get the white down triangle working without an issue but how do I place yet another triangle (green lines) over the top of the first one without a full border/background or using an image? I can only get a solid green arrow over the white one and that's not what I want to do.

This is what I currently have.

 .custom-nav li a:after { 
    content: ""; 
    z-index: 99; 
    width: 0; 
    height: 0; 
    border-style: solid; 
    border-width: 40px 150px 0 150px; 
    border-color: #ffffff transparent transparent transparent; 
    position: absolute; 
    top: 173%; left: -75px; 
}
<div>
  <ul class="custom-nav">
    <li><a href="#">Environment</a></li>
    <li><a href="#">Health</a></li>
  </ul>
</div>

Upvotes: 3

Views: 161

Answers (2)

Temani Afif
Temani Afif

Reputation: 272723

Multiple background can do this:

.box {
  --w:160px; /* width of the arrow */
  --h:40px;  /* height of the arrow*/
  --b:2px;   /* thickness of the green arrow */
  --o:20%;   /* offset of the green arrow */
  
  /* gadient coloration, white then the green border then white again then transparent */
  --g:#fff var(--o),
      green var(--o) calc(var(--o) + var(--b)),
      #fff calc(var(--o) + var(--b) + 1px) 49.8%,
      transparent 50%;

  height:50px;
  margin:5px;
  border-bottom:var(--h) solid transparent; /* the arrow will take the border space */
  background:
    linear-gradient(to bottom right,var(--g)) calc(50% + calc(var(--w)/4)) 100% border-box,
    linear-gradient(to bottom left ,var(--g)) calc(50% - calc(var(--w)/4)) 100% border-box,
    #fff padding-box;
  background-size:calc(var(--w)/2) var(--h);
  background-repeat:no-repeat;
}


body {
  background:#000;
}
<div class="box"></div>

<div class="box" style="--w:200px;--h:60px;--o:30%;--b:5px"></div>

<div class="box" style="--w:180px;--h:30px;--o:10%;--b:3px"></div>

Upvotes: 2

Danziger
Danziger

Reputation: 21161

I think the best option to get something like that is to use an SVG:

body {
  margin: 0;
  background: #DEE;
}

.nav {
  display: flex;
}

.button {
  position: relative;
  background: transparent;
  border: 0;
  width: 50%;
  height: 100px;
  padding: 0 0 50px;
  background: content-box white;
  font-family: monospace;
  font-weight: bold;
  outline: none;
  cursor: pointer;
}

.button__text {
  position: relative;
  z-index: 1;
}

.button__triangle {
  position: absolute;
  top: 25px;
  bottom: 0;
  left: 50%;
  width: 100%;
  transition: transform ease-in 150ms;
  transform: translate(-50%, -50%);
}

.button:hover > .button__triangle {
  transform: translate(-50%, 0);
}

.button__triangle--big {
  fill: white;
}

.button__triangle--small {
  fill: white;
  stroke: red;
  stroke-width: 2px;
  stroke-linecap: round;
  opacity: 0;
  transition: opacity ease-in 150ms;
}

.button:hover .button__triangle--small {
  opacity: 1;
}
<nav class="nav">
  <button class="button">
    <span class="button__text">OPTION 1</span>
    
    <svg viewBox="0 0 200 50" class="button__triangle">
      <polygon points="0,0 100,50 200,0" class="button__triangle--big" />
      <polyline points="50,5 100,30 150,5" class="button__triangle--small" />
    </svg>
  </button>
  
  <button class="button">
    <span class="button__text">OPTION 2</span>
    
    <svg viewBox="0 0 200 50" class="button__triangle">
      <polygon points="0,0 100,50 200,0" class="button__triangle--big" />
      <polyline points="50,5 100,30 150,5" class="button__triangle--small" />
    </svg>
  </button>
</nav>

Upvotes: 2

Related Questions