7

I'm looking for an easy way with a single tag (just <a>)to create a skew effect on the borders, but keep the text the way it is.

I would know how do with a span in- or outside, but I don't want to have additional, pretty much zero meaning HTML on the page.

Example below.

enter image description here

Sander Schaeffer
  • 2,757
  • 7
  • 28
  • 58

4 Answers4

5

You can unskew the child element i.e. provide the opposite skew co-ordinates as you specified for the parent.

Here is a working example

Suppose you have below as you html,

<div class="btn">
    <button><div class="btn-text">Click</div></button>
</div>

If we skew the parent element by 20deg then we should skew the child element by -20deg as,

.btn {
    -ms-transform: skewX(20deg); /* IE 9 */
    -webkit-transform: skewX(20deg); /* Safari */
    transform: skewX(20deg);
}
.btn-text {
    -ms-transform: skewX(-20deg); /* IE 9 */
    -webkit-transform: skewX(-20deg); /* Safari */
    transform: skewX(-20deg);
    padding: 20px;
}
Saumil
  • 2,521
  • 5
  • 32
  • 54
  • i like this answer too, two good answers to the same problem, though I'd probably go for css triangles as it's less HTML :-P – Toni Leigh Jun 11 '15 at 06:28
  • Just a guess but, wouldn't it be easier to have the html be like text? This way you don't have two separate HTML classes/elements (span is none). The CSS could remain the same, however. Besides that: Use classes, not ID's. :) Thanks for your input tho! – Sander Schaeffer Jun 11 '15 at 09:44
  • With a bit of help of your CSS, I used the span-method as I suggested above. I had to add 'display: inline-block' for both the anchor and the span element, as they're not inline elements. But it works great now! :) – Sander Schaeffer Jun 11 '15 at 10:17
  • @SanderSchaeffer - classes are probably best, then you can re-use the style on other elements and it doesn't cause a problem if you decide to change the internal element for some reason, i.e. ` – Toni Leigh Jun 11 '15 at 11:37
  • @SanderSchaeffer Tony Leigh, yeah classes are much better when you want to reuse stuff, I have a bad habit for not sometimes thinking of class reuse. Updated the answer. – Saumil Jun 11 '15 at 15:43
5

You can simply accompish desired effect using CSS triangle tricks. Just add some styles for the ::before and :: after pseudo-classes.

.skewed_button {
    background: #32CD32;
    color: #000;
    text-decoration: none;
    font-size: 20px;
    display: inline-block;
    height: 30px;
    margin-left: 15px;
    padding: 6px 10px 0;
}
.skewed_button::before {
    content: "";
    float: left;
    margin: -6px 0 0 -25px;
    border-left: 15px solid transparent;
    border-bottom: 36px solid #32CD32;  
    height: 0px;
}
.skewed_button::after {
    content: "";
    float: right;
    margin: -6px -25px 0 0 ;
    border-left: 15px solid #32CD32;
    border-bottom: 36px solid transparent;  
    height: 0px;
}
<a href="#some_url" class="skewed_button">Some Text</a>
Vadym Pechenoha
  • 574
  • 5
  • 17
  • why is one border white and one transparent? also, why is there -6px of top margin and differing amounts of left and right margins on each triangle? – Toni Leigh Jun 11 '15 at 06:27
  • It was just a mistake. I've changed it to transparent. There're differing margins for top and left/right margins, because we need the vertical align of a text set to center, so top margin shoud be added (with -6px it looks nice). And -25px for left/right: 15px - it's the size of triangle, and 10px - just add some space between text and triangles. – Vadym Pechenoha Jun 11 '15 at 08:54
  • I assume it's not possible to have it automatically equal the height of the button itself? Most likely, all buttons will have the same height, as the font size does not change.. but still. That would be nice. – Sander Schaeffer Jun 11 '15 at 09:42
  • @SanderSchaeffer possibly - see the first js fiddle in my answer - try changing the values to % and see what happens, though I'm not sure about the widths on the psuedo elements, what would they compare to ? Vw units might work though, if they were used on the button too and you didn't mind the size changing with the viewport! – Toni Leigh Jun 11 '15 at 10:42
  • It is ok but wont scale well. If you need to have responsive text etc, then it gonna include some degree of pain to maintain – GorillaApe Apr 10 '16 at 19:33
3

You can also use clip-path for this, eg:

clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);

.skewed_button {
    background: yellow;
    text-decoration: none;
    display: inline-block;
    padding: 10px 20px;
    clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);
}
<a href="" class="skewed_button">Some Text</a>
uNmAnNeR
  • 600
  • 5
  • 12
2

One solution is to use css triangles on :before and :after. This solution leaves the cleanest HTML.

This jsfiddle demonstrates

.is-skewed {
    width: 80px;
    height: 40px;
    background-color: #f07;
    display: block;
    color: #fff;
    margin-left: 40px;
}

.is-skewed:before,
.is-skewed:after {
    content: '';
    width: 0;
    height: 0;
}

.is-skewed:before {
    border-bottom: 40px solid #f07;
    border-left: 20px solid transparent;
    float:left;
    margin-left: -20px;
}

.is-skewed:after {
    border-top: 40px solid #f07;
    border-right: 20px solid transparent;
    float:right;
    margin-right: -20px;
}

CSS triangles use thick borders on elements with 0 dimensions with the points at which the borders meet providing the diagonal line required for a triangle (a good visualisation is to look at the corner of a picture frame, where the two borders meet and create triangles). It's important that one border is transparent and one coloured and that they are adjacent (i.e. left and top, not left and right). You can adjust the size, orientation and the lengths of the sides by playing with the border sizes.

For your button, we also use floats and negative margins to pull them outside of the element and line them up right. Position absolute and negative left and right values would also be a good solution to positioning

You can also do :hover states

.is-skewed:hover {
    background-color: #40f;
}
.is-skewed:hover:after {
    border-top-color: #40f;    
}
.is-skewed:hover:before {
    border-bottom-color: #40f;
}

It's important to note the use of background-color and border-color and also that the :hover comes first in all the relevant selectors. If the hover came second this would happen

Toni Leigh
  • 4,830
  • 3
  • 22
  • 36