Search code examples
htmlcssbuttoncss-shapes

div with slanted side and rounder corners


I am currently building a website which requires buttons to have a slant on the left hand side of the button. The website is responsive and the button requires rounded corners too. I am trying to avoid using background images too.

Would someone be able to show me a solution to this? Ignore the icon on the button, I am able to do this. I just need the slanted side.

div with slanted side and rounded corners

Sample jsfiddle

body {
  background: lightblue;
  font-family: sans-serif;
}
div {
  background: purple;
  width: 200px;
  padding: 30px;
  border: 3px solid white;
  color: white;
}
<div>Some Text</div>


Solution

  • Note: I am adding a separate answer because though the answers that I linked in comment seem to give a solution, this one is a bit more complex due to the presence of border also along with the border-radius.

    The shape can be created by using the following parts:

    • One main container element which is positioned relatively.
    • Two pseudo-elements which are roughly half the width of parent element. One element is skewed to produce the skewed left side whereas the other is not skewed.
    • The skewed pseudo-element is positioned at the left while the normal element is positioned at the right of the container element.
    • The skewed pseudo-element has only top, left and bottom borders. The right border is omitted as it would come right in the middle of the shape. For the pseudo-element that is not skewed, the left border is avoided for the same reason.
    • Left border of the skewed pseudo-element is a bit more thicker than other borders because skew makes the border look thinner than it actually is.

    I have also added a hover effect to the snippet to demonstrate the responsive nature of the shape.

    .outer {
      position: relative;
      height: 75px;
      width: 300px;
      text-align: center;
      line-height: 75px;
      color: white;
      text-transform: uppercase;
    }
    .outer:before,
    .outer:after {
      position: absolute;
      content: '';
      top: 0px;
      height: 100%;
      width: 55%;
      background: purple;
      border: 2px solid white;
      border-left-width: 3px;
      z-index: -1;
    }
    .outer:before {
      left: 0px;
      border-radius: 20px;
      border-right: none;
      transform: skew(20deg);
      transform-origin: top left;
    }
    .outer:after {
      right: 0px;
      border-top-right-radius: 20px;
      border-bottom-right-radius: 20px;
      border-left: none;
    }
    
    /* Just for demo of responsive nature */
    
    .outer{
      transition: all 1s;
    }
    .outer:hover{
      height: 100px;
      width: 400px;
      line-height: 100px;
    }
    body{
      background: lightblue;
    }
    <div class='outer'>
      Call me back
    </div>

    Advantage:

    • A big advantage of this approach is that it provides a graceful fallback. That is, in non CSS3 compliant browsers it would look like normal button with rounded corners (and no slanted side).
    • The page (or container element) background need not be a solid color.
    • The shape itself can have non-solid colors (that is, images or gradients) as background. It would need some extra tweaking but the approach itself will remain same.

    In the below snippet, I have given each component a different color to visually illustrate how the shape is achieved:

    .outer {
      position: relative;
      height: 75px;
      width: 300px;
      text-align: center;
      line-height: 75px;
      color: white;
      text-transform: uppercase;
    }
    .outer:before,
    .outer:after {
      position: absolute;
      content: '';
      top: 0px;
      height: 100%;
      width: 55%;
      background: purple;
      border: 2px solid white;
      border-left-width: 3px;
      z-index: -1;
    }
    .outer:before {
      left: 0px;
      border-radius: 20px;
      border-right: none;
      transform: skew(20deg);
      transform-origin: top left;
      background: seagreen;
      border-color: red;
    }
    .outer:after {
      right: 0px;
      border-top-right-radius: 20px;
      border-bottom-right-radius: 20px;
      border-left: none;
      background: yellowgreen;
      border-color: maroon;
    }
    
    /* Just for demo of responsive nature */
    
    .outer{
      transition: all 1s;
    }
    .outer:hover{
      height: 100px;
      width: 400px;
      line-height: 100px;
    }
    body{
      background: lightblue;
    }
    <div class='outer'>
      Call me back
    </div>