82

Is it possible to reproduce this image using only CSS?

enter image description here

I want to apply this to my menu, so the brown background appears on hover instance

I don't know how to do this, I only have;

.menu li a:hover{
     display:block;
     background:#1a0000;
     padding:6px 4px;
}
zvava
  • 101
  • 1
  • 3
  • 14
Preston
  • 2,135
  • 7
  • 29
  • 47

7 Answers7

156

skew a parent element (li in this example) and inverse skew its child elements:

CSS Menu skewed buttons diagonal borders

nav ul {
  padding: 0;
  display: flex;
  list-style: none;
}
nav li {
  transition: background 0.3s, color 0.3s;
  transform: skew(20deg); /* SKEW */
}

nav li a {
  display: block; /* block or inline-block is needed */
  text-decoration: none;
  padding: 5px 10px;
  font: 30px/1 sans-serif;
  transform: skew(-20deg); /* UNSKEW */
  color: inherit;
}

nav li.active,
nav li:hover {
  background: #000;
  color: #fff;
}
<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li class="active"><a href="#">Products</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>
temporary_user_name
  • 35,956
  • 47
  • 141
  • 220
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • yeah... and thanks too to Reformulate my question.. i don't remember that `skew` name.. :) – Preston Jul 30 '13 at 13:24
  • 1
    this: `display:inline-block;` don't work IE8 or less... so i put some `*float:left;` hack to make this "inline" on IE. But when i mouse over the menu, (on IE8) i can't setup some normal background (without the skew). Any tips? – Preston Jul 30 '13 at 13:45
  • @Preston sure, use images and help us kill IE8 – Roko C. Buljan Jul 30 '13 at 17:40
  • That only works if you have an element nested inside, I'd like to just effect the text. – JackHasaKeyboard Nov 05 '16 at 10:41
  • 1
    @JackHasaKeyboard you cannot; so wrap your text into a `` and do the same. – Roko C. Buljan Nov 05 '16 at 11:14
  • @RokoC.Buljan <--- what he said. Please.... nobody ever do this in practice... just wrap it in a span and give it those same skew properties and maybe a `display: inline-block` or something. – Eric Hodonsky Jun 30 '20 at 19:12
  • I could not revert the skew of a `span` child. Had to use a `div` instead. Possibly something to do with the `display` property though, not sure. – Slion Jul 02 '22 at 14:10
10

Here is a fiddle for use across different browsers - I created in a couple of minutes.

Try playing with the arguments, I used :before and :after to do this.

https://jsfiddle.net/DTBAE/

zvava
  • 101
  • 1
  • 3
  • 14
udidu
  • 8,269
  • 6
  • 48
  • 68
6

You can use the transform: skew(X, Y) property to achieve this. Creating a skewed outer container, then skew the opposite amount on an inner container to skew the text back to being straight. See this fiddle for example;

http://jsfiddle.net/UZ6HL/4/

From what you have said, I believe this is what you want, if not please clarify when the item should display the background.

zvava
  • 101
  • 1
  • 3
  • 14
Don
  • 3,987
  • 15
  • 32
4

.skew {
  background: green;
  color: #fff;
  padding: 50px;
  transform: skewX(-7deg);
  font-size: 20px;
  font-weight: 700;
}

.skew p {
  transform: skewX(7deg);
}
<div class="skew">
  <p>This is caption</p>
</div>

Here's an example

lurk
  • 41
  • 1
2

To have IE support just add -ms-transform: skew(20deg, 0deg); beside all the other transform: skew(20deg, 0deg);s.

zvava
  • 101
  • 1
  • 3
  • 14
1

You can use clip-path to make results like these. For example:

* {
  box-sizing: border-box;
}

body {
  padding: 0;
  margin: 0;
}

ul {
  display: flex;
  width: 100%;
  flex-direction: row;
  gap: 20px;
  background: #000;
  padding: 0 10px;
  justify-content: flex-end;
}

li {
  list-style-type: none;
  clip-path: polygon(20% 0%, 100% 0, 80% 100%, 0% 100%);
  background: blue;
  padding: 10px 50px;
}

a {
  color: #fff;
}
<ul>
  <li><a href="">Home</a></li>
  <li><a href="">About</a></li>
</ul>

You can generate your clip from here and use it in your code.

Here is a working Fiddle for reference

Ahmad Habib
  • 2,053
  • 1
  • 13
  • 28
0

NOTE: SPAN is NOT affected by transform CSS functionality, so you will need a DIV or change span to display: block; otherwise they will NOT be affected.

So just put the TEXT inside a separate div and unskew it.

example wrapper div is:

 transform: skewx(35deg)

but text div is:

transform: skewx(-35deg); 

here is codepen: https://codepen.io/dmitrisan/pen/NWaYEzV

fruitloaf
  • 1,628
  • 15
  • 10