4

enter image description here

Is it possible to create a responsive arrow like in the image that adapts to the height (aka the left columns second paragraph is deleted) with css only? I tried with borders, rotated and skewed padding and box shadows. But wasn't able to achieve the layout as seen in the image. My problem is the variable height of the "element".

This is the html code implemented:

<div class="container">
  <div class="row">
    <article class="col-container">
      <div class="col-md-6 col-xs-6 col-left">
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
          porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
        <p>Sed volutpat fringilla tempus. Quisque sit amet elit non ante facilisis accumsan. Phasellus varius facilisis eleifend. Sed iaculis arcu magna, ut ullamcorper diam venenatis eget. Pellentesque iaculis risus vitae augue ultricies accumsan. Etiam
          vulputate, ante a blandit luctus, sapien augue scelerisque ligula, id rhoncus massa arcu eget eros. Ut et nisl eu purus ullamcorper suscipit. Pellentesque in suscipit ipsum, quis auctor augue. Vestibulum non aliquet ipsum, sed luctus nibh. Praesent
          vulputate efficitur augue, eu mattis metus porttitor pharetra.
        </p>
      </div>
      <div class="col-md-6 col-xs-6 col-right">
        <p>
          In placerat nulla non mauris dictum ullamcorper. Integer elementum ipsum sit amet lacus imperdiet mollis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pulvinar, mi ac laoreet consectetur, lorem mi congue
          augue, a pellentesque erat neque eu purus.
        </p>
      </div>
    </article>
  </div>
</div>

And this the css:

.col-container {
  overflow: hidden;
  position: relative;
}

.col-left,
.col-right {
  margin-bottom: -9999px;
  padding-bottom: 9999px;
}

.col-left {
  background-color: #fff;
}

.col-right {
  background-color: #019CDC;
}

I made a jsfiddle to play around here: https://jsfiddle.net/ae6L4or5/

web-tiki
  • 99,765
  • 32
  • 217
  • 249
steros
  • 1,794
  • 2
  • 26
  • 60

3 Answers3

4

clip-path Solution

This is achievable with the CSS property clip-path.

This is still fairly unsupported and as such should be used more as a future recommendation

.col-container {
  overflow: auto;
  box-sizing: border-box;
  background: skyblue;
}
.col-container .col-left {
  background: white;
  -webkit-clip-path: polygon(80% 0, 95% 50%, 80% 100%, 0 100%, 0 0);
  clip-path: polygon(80% 0, 95% 50%, 80% 100%, 0 100%, 0 0);
  width: 60%;
  float: left;
  padding: 12px;
  padding-right: 12%;
  box-sizing: border-box;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
  <div class="row">
    <article class="col-container">
      <div class="col-md-8 col-xs-8 col-left">
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
          porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
        <p>Sed volutpat fringilla tempus. Quisque sit amet elit non ante facilisis accumsan. Phasellus varius facilisis eleifend. Sed iaculis arcu magna, ut ullamcorper diam venenatis eget. Pellentesque iaculis risus vitae augue ultricies accumsan. Etiam
          vulputate, ante a blandit luctus, sapien augue scelerisque ligula, id rhoncus massa arcu eget eros. Ut et nisl eu purus ullamcorper suscipit. Pellentesque in suscipit ipsum, quis auctor augue. Vestibulum non aliquet ipsum, sed luctus nibh. Praesent
          vulputate efficitur augue, eu mattis metus porttitor pharetra.
        </p>
      </div>
      <div class="col-md-4 col-xs-4 col-right">
        <p>
          In placerat nulla non mauris dictum ullamcorper. Integer elementum ipsum sit amet lacus imperdiet mollis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pulvinar, mi ac laoreet consectetur, lorem mi congue
          augue, a pellentesque erat neque eu purus.
        </p>
      </div>
    </article>
  </div>
</div>

Stewartside
  • 20,378
  • 12
  • 60
  • 81
  • This is good, but when the user clicks the `clip-path` property support he will be discouraged to use this in production, and he should. – Ricky Ruiz Oct 06 '16 at 15:04
  • 1
    @Ricky_Ruiz very true so I have added a little disclaimer in there. Gonna work on an additional answer for the OP too :) – Stewartside Oct 06 '16 at 15:06
  • Yeah it is nice, never heard of it yet. The problem really is the compatibility. – steros Oct 06 '16 at 15:16
3

SVG Solution:

You can achieve this using SVG:


MARKUP:

First lets create our SVG shape using the <path> tag. It is important to add the attribute fill with a value of currentColor which will be explained below in a few more steps.

<path fill="currentColor" d="M0 0 L0 100 L35 50 Z"></path>

More info: <path> tag here.


After creating our "triangle" shape, we will wrap it in a <symbol> tag with an id for us to be able to use it multiple times just like SVG Icons, with a spritesheet and using the <use> tag.

<svg id="spriteSheet">
<defs>
  <symbol id="triangleSeparator" viewBox="0 0 100 100" preserveAspectRatio="none">
    <path fill="currentColor" d="M0 0 L0 100 L35 50 Z"></path>
  </symbol>
</defs>
</svg>

The <use> element lets you reuse existing elements, giving you a similar functionality to the copy-paste functionality in a graphics editor.

More info: here.


Okay, so now we got our SVG ready for use (pun inteded). Lets wrap it in a <svg> tag and add a class to it to style it later.

<svg class="separator__triangle">
   <use xlink:href="#triangleSeparator"></use>
</svg>

Next, wrap the above <svg> tag with another element for us to position it like we want.

<div class="separator__container">
    <svg class="separator__triangle">
      <use xlink:href="#triangleSeparator"></use>
    </svg>
</div>

STYLING:

Remember the value currentColor we defined in our <path> attribute fillin the beginning?

It's time to use it, currentColor variable will follow the cascade and get the value from our color property defined in the following class:

.separator__triangle {
  width: 100px; /* You can change the width if you want it to be bigger or smaller*/
  height: 100% /* Used to fill the whole container */;
  color: white; /* This is the color of the triangle shape */
}

Positioning our container and hiding our spritesheet (this is needed to prevent it from rendering an empty space):

#spriteSheet {
  display: none;
}

.separator__container {
  pointer-events: none; /* We don't want it to have any pointer events do we?*/
  position: absolute; /* Positioning */
  top: 0;
  left: 0;
  height: 100%; /* Cover whole height of the container*/
}

Finally, we are ready to go!

CODE SNIPPET:

.container {
  display: flex;
}
.col {
  padding: 3em;
}
.col--left {
  background-color: #fff;
}
.col--right {
  background-color: #019CDC;
}
.col--with-separator {
  position: relative;
}
#spriteSheet {
  display: none;
}
.separator__container {
  pointer-events: none;
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
}
.separator__triangle {
  width: 100px;
  height: 100%;
  color: white;
}
<main>
  <article class="container">
    <section class="col col--left">
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
        porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
      <p>Sed volutpat fringilla tempus. Quisque sit amet elit non ante facilisis accumsan. Phasellus varius facilisis eleifend. Sed iaculis arcu magna, ut ullamcorper diam venenatis eget. Pellentesque iaculis risus vitae augue ultricies accumsan. Etiam vulputate,
        ante a blandit luctus, sapien augue scelerisque ligula, id rhoncus massa arcu eget eros. Ut et nisl eu purus ullamcorper suscipit. Pellentesque in suscipit ipsum, quis auctor augue. Vestibulum non aliquet ipsum, sed luctus nibh. Praesent vulputate
        efficitur augue, eu mattis metus porttitor pharetra.
      </p>
    </section>
    <section class="col col--right col--with-separator">
      <div class="separator__container">
        <svg class="separator__triangle">
          <use xlink:href="#triangleSeparator"></use>
        </svg>
      </div>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
        porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
    </section>
  </article>
</main>

<svg id="spriteSheet">
  <defs>
    <symbol id="triangleSeparator" viewBox="0 0 100 100" preserveAspectRatio="none">
      <path fill="currentColor" d="M0 0 L0 100 L35 50 Z"></path>
    </symbol>
  </defs>
</svg>

Remember that whenever you want to use the arrow, you will just need to add the following to your container:

<div class="separator__container">
    <svg class="separator__triangle">
       <use xlink:href="#triangleSeparator"></use>
    </svg>
</div>

Note: Your container must have position: relative; as one of its CSS properties, because our arrow is positioned using the absolute value.


PLAYGROUND:

Lets add a modifier to invert the arrow and use it on the left column!

.container {
  display: flex;
}
.col {
  padding: 3em;
}
.col--left {
  background-color: #fff;
}
.col--right {
  background-color: #019CDC;
}
.col--with-separator {
  position: relative;
}
#spriteSheet {
  display: none;
}
.separator__container {
  pointer-events: none;
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
}
.separator__triangle {
  width: 100px;
  height: 100%;
  color: white;
}
.separator__container--inverted {
  left: calc(100% - 100px);
}
.separator__container--inverted .separator__triangle {
  color: #019CDC;
  transform: rotateZ(180deg);
}
<main>
  <article class="container">
    <section class="col col--left col--with-separator">
      <div class="separator__container separator__container--inverted">
        <svg class="separator__triangle separator__triangle--inverted">
          <use xlink:href="#triangleSeparator"></use>
        </svg>
      </div>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
        porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
      <p>Sed volutpat fringilla tempus. Quisque sit amet elit non ante facilisis accumsan. Phasellus varius facilisis eleifend. Sed iaculis arcu magna, ut ullamcorper diam venenatis eget. Pellentesque iaculis risus vitae augue ultricies accumsan. Etiam vulputate,
        ante a blandit luctus, sapien augue scelerisque ligula, id rhoncus massa arcu eget eros. Ut et nisl eu purus ullamcorper suscipit. Pellentesque in suscipit ipsum, quis auctor augue. Vestibulum non aliquet ipsum, sed luctus nibh. Praesent vulputate
        efficitur augue, eu mattis metus porttitor pharetra.
      </p>
    </section>
    <section class="col col--right">
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
        porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
    </section>
  </article>
</main>

<svg id="spriteSheet">
  <defs>
    <symbol id="triangleSeparator" viewBox="0 0 100 100" preserveAspectRatio="none">
      <path fill="currentColor" d="M0 0 L0 100 L35 50 Z"></path>
    </symbol>
  </defs>
</svg>

JSFIDDLE


This is an alternative to Stewartside solution, lacking browser support at the moment.


EDIT:

Adressing the problem you have with equal height columns, Flexbox is used in the demo, which further explanation is not included in the scope of this answer.

However, here's another post where you can find useful resources on flexbox in the more info section.

Community
  • 1
  • 1
Ricky Ruiz
  • 25,455
  • 6
  • 44
  • 53
2

You can use :before and :after pseudo elements and a little bit CSS3 transformation to achieve this.

Note: This technique is depends on content of the largest column. You can change width of pseudo elements and a bit rotation to make it fit for your needs.

@import url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css');

.col-container {
  overflow: hidden;
  position: relative;
  background: #fff;
}

.col-left,
.col-right {
  margin-bottom: -9999px;
  padding-bottom: 9999px;
}

.col-left {
  z-index: 10;
}

.col-right {
  background-color: #019CDC;
  padding-left: 50px;
}

.col-container:before,
.col-container:after {
  transform: rotate(3deg);
  transform-origin: 0 0;
  position: absolute;
  margin-left: -15px;
  background: #fff;
  margin-top: -3px;
  height: 9999px;
  content: '';
  width: 50px;
  z-index: 1;
  bottom: 0;
  left: 50%;
  top: 50%;
}
.col-container:before {
  transform-origin: 0 100%;
  transform: rotate(-3deg);
  margin-bottom: -3px;
  bottom: 50%;
  top: auto;
}
<div class="container">
  <div class="row">
    <article class="col-container">
      <div class="col-md-6 col-xs-6 col-left">
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque maximus eu justo at viverra. Sed sollicitudin semper lectus, et placerat magna hendrerit vel. Nunc ac ipsum non neque dictum congue. Nunc ligula libero, tempus vitae magna eu, ultrices
          porta est. Vivamus et turpis scelerisque, vehicula tellus in, feugiat augue. Aliquam egestas massa id leo suscipit, id venenatis tellus dictum. Sed ante eros, iaculis a diam in, dapibus sagittis ipsum. Sed in eros id odio ornare interdum.</p>
        <p>Sed volutpat fringilla tempus. Quisque sit amet elit non ante facilisis accumsan. Phasellus varius facilisis eleifend. Sed iaculis arcu magna, ut ullamcorper diam venenatis eget. Pellentesque iaculis risus vitae augue ultricies accumsan. Etiam
          vulputate, ante a blandit luctus, sapien augue scelerisque ligula, id rhoncus massa arcu eget eros. Ut et nisl eu purus ullamcorper suscipit. Pellentesque in suscipit ipsum, quis auctor augue. Vestibulum non aliquet ipsum, sed luctus nibh. Praesent
          vulputate efficitur augue, eu mattis metus porttitor pharetra.
        </p>
      </div>
      <div class="col-md-6 col-xs-6 col-right">
        <p>
          In placerat nulla non mauris dictum ullamcorper. Integer elementum ipsum sit amet lacus imperdiet mollis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pulvinar, mi ac laoreet consectetur, lorem mi congue
          augue, a pellentesque erat neque eu purus.
        </p>
      </div>
    </article>
  </div>
</div>
Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95