JP4
JP4

Reputation: 1176

CSS Custom Shape With Border

I'm trying to make a menu with tabs. The style of the tabs is like so:

enter image description here

I need the background to be transparent and have a border, on hover, it will fill the background with another color.

I have tried to do this with pure CSS, I can get the shape correct using :before and :after, however as I'm using borders to do this, I cannot add a border on both sides and end up with this:

enter image description here

#pointer {
  width: 200px;
  height: 40px;
  position: relative;
  background: red;
  text-align: centre;
  border: 1px solid white;
}

#pointer:after {
  content: "";
  position: absolute;
  left: -20px;
  bottom: 0;
  width: 0;
  margin-bottom: 20px;
  height: 0;
  border-right: 20px solid red;
  border-top: 0px solid red;
  border-bottom: 20px solid transparent;
}

#pointer:before {
  content: "";
  position: absolute;
  right: -20px;
  bottom: 0;
  width: 0;
  height: 0;
  border-left: 20px solid red;
  border-top: 20px solid transparent;
  border-bottom: 20px solid red;
}
<div id="pointer">Tab 1</div>

I have also tried to do this with SVG, I can get the shape and border correct, but the hover area is a lot larger then the border.

    <svg
      class="test"
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 64 64'
      width='150' height='150'
      stroke='white'
      fill='red'>
      <path d='M8 30 L62 30 L62 22 L56 16 L2 16 L8 22 Z' />
    </svg>

How can I either, complete the borders with CSS attempt, or make the hover area of the SVG match the border exactly?

Upvotes: 2

Views: 618

Answers (2)

Temani Afif
Temani Afif

Reputation: 272742

Here is a simple idea considering skew transformation:

.box {
  width: 200px;
  height: 80px;
  margin: 20px;
  color:#fff;
  z-index:0;
  position: relative;
  --c: black;
  --b: red;
}

.box:hover {
  --b: blue;
  --c:green;
}

.box:before,
.box:after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  right: 0;
  height: 50%;
  border: 3px solid var(--c);
  background: var(--b);
  box-sizing:border-box;
}

.box:before {
  top: 0;
  transform: skewX(30deg);
  transform-origin: bottom right;
  border-bottom: none;
}

.box:after {
  bottom: 0;
  border-top: none;
}
<div class="box">
  some text
</div>

And for your SVG shape you simply need to reduce the viewBox to cover only your shape:

svg {
  border:1px solid
}
svg:hover path{
 stroke:red;
 fill:blue;
}
 <svg
      class="test"
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 14 64 18'
      width="150"
      stroke='blue'
      stroke-width=2
      fill='red'>
      <path d='M8 30 L62 30 L62 22 L56 16 L2 16 L8 22 Z' />
    </svg>

Upvotes: 2

Gerardo BLANCO
Gerardo BLANCO

Reputation: 5648

For complex shpaes, it is allways better to use svg.

What I get from your problem, is that the svg area/ hover area is bigger than the figgure. And this is true. But you can solve this by targeting the path inside the svg to make your style whet path:hover.

I made a small snippet so you can see how it works.

Hope this helps :>

svg {
  background: red;
}

svg:hover {
  background: orange;
}

path:hover {
  fill: blue;
}
<svg
  class="test"
  xmlns='http://www.w3.org/2000/svg'
  viewBox='0 0 64 64'
  width='150' height='150'
  stroke='white'
  fill='green'>
  <path d='M8 30 L62 30 L62 22 L56 16 L2 16 L8 22 Z' />
</svg>

Upvotes: 1

Related Questions