12

enter image description here

Is it possible to make something like that in CSS? I want an image for the header, but I want that triangle cut out of the next section so the image above shows there.

I know how to make a solid CSS triangle with borders (something like this for example: http://www.dailycoding.com/Posts/purely_css_callouts.aspx), but in this case I either need to do the opposite (take a "chunk" out of the blue part), or make the triangle an image that somehow lines up exactly with the image it is connected to. I'm thinking if I can take a "chunk" out, that might be easier

To make it a little more complicated, I also have the image above set to background-attachment: fixed and background-size: cover. So the image scales as the browser size is made larger.

If I can't do it with CSS alone and need an image, how can I make the right combinations of images to keep the triangle in line with the text if the text is centered horizontally on the page? I'm thinking something like this with two long div's that extend into the margins, and one exact width image in the middle with the triangle transparent:

_____________________________  ___ ______________________  _________________________
|    (really wide for margin)||   V (960px wide image)   || (really wide box again) |

But can it be done with just CSS? Or is there perhaps an SVG solution (I'm not as familiar with SVG)? I'm okay with a solution that only works in modern browsers as this is definitely just "progressive enhancement".

Matt
  • 5,478
  • 9
  • 56
  • 95

3 Answers3

10

Here's a twist on the triangles-from-borders concept.

HTML

<div id="container">
    <div id="one"></div>
    <div id="two"></div>
</div>

CSS

#container{
    height: 300px;
    background-color: red;
    position: relative;
}

#one {
    position: absolute;
    width: 100px;
    left: 0;
    bottom: 0;
    border-bottom: 20px solid green;
    border-right: 20px solid transparent;
}

#two {
    position: absolute;
    left: 120px;
    bottom: 0;
    right: 0;
    border-bottom: 20px solid green;
    border-left: 20px solid transparent;
}

An alternative: I've done something similar with CSS transforms (specifically, skew). See CSS (3) & HTML Cut edge.

Community
  • 1
  • 1
Tim M.
  • 53,671
  • 14
  • 120
  • 163
  • I was working on a answer using more of z-index but i think this will suit the OP more – MarsOne Aug 22 '13 at 07:42
  • 1
    You can also use `(:):before`/`(:):after` pseudo-elements instead of `#one`/`#two`, in order to keep the markup cleaner: http://jsfiddle.net/V2yyH/ – Ilya Streltsyn Aug 22 '13 at 08:19
  • You should post that as an answer (along with your other improvements). I'll upvote it. – Tim M. Aug 22 '13 at 08:24
  • I was happy when it handled `background-size: cover` and `background-attachment: fixed` :) http://jsfiddle.net/nhqKb/4/ – Matt Aug 23 '13 at 06:20
3

You can do it without much extra markup at all using ::before and ::after. You just need overflow: hidden on the container.

Given

<div class="hero">
  <img src="http://farm3.staticflickr.com/2431/3875936992_348d6dd86b_b.jpg" alt=""/>
</div>

The CSS would be

.hero {
    position: relative;
    overflow: hidden;
}
.hero img {
    display: block;
    width: 960px;
    height: auto;
}
.hero::before {
    content: "\00A0";
    display: block;
    border: 960px solid #fff; /* the width of the image */
    border-top-width: 0;
    border-bottom-width: 0;
    height: 30px; /* 1/2 the triangle width */
    width: 60px; /* the triangle width */
    position: absolute;
    bottom: 0;
    left: -630px; /* the left offset - the image width */
}
.hero::after {
    content: "\00A0";
    display: block;
    border: 30px solid #fff; /* 1/2 the triangle width */
    border-top: 30px solid transparent; /* 1/2 the triangle width */
    border-bottom-width: 0;
    height: 0;
    width: 0;
    position: absolute;
    bottom: 0;
    left: 330px; /* the left offset */
}

Live example: http://codepen.io/aarongustafson/full/nutDB

Aaron Gustafson
  • 602
  • 6
  • 11
  • I would vote for this with the `::before` and `::after`, but it used an `img` instead of `background`. Still, up vote from me! Thanks! – Matt Aug 23 '13 at 06:21
0

I worked on this in a different way. Not exactly what the op wants but looks good and may help somebody else.

I have used z-index and border-radius to achieve this effect

DEMO

HTML

<div>
    <img src="http://lorempixel.com/500/200/sports/" class="lowerpic"/>
    <div class="leftupperdiv"></div>
    <div class="rightupperdiv"></div>
</div>

CSS

.lowerpic {
    z-index:-1;
    position:absolute;
}
.leftupperdiv {
    z-index:1;
    position:absolute;
    margin-top:150px;
    width:100px;
    height:50px;
    border-radius: 0px 30px 0px 0px;
    background-color: blue;
}
.rightupperdiv {
    z-index:1;
    position:absolute;
    margin-top:150px;
    margin-left:100px;
    width:400px;
    height:50px;
    border-radius: 30px 0px 0px 0px;      
    background-color: blue;
}
MarsOne
  • 2,155
  • 5
  • 29
  • 53