2

I'm trying to recreate this layout in HTML/CSS (cross-browser compatible back to IE9):

diagonally split background pattern

Basically, it's a diagonal line spanning the width of the viewport that divides two background patterns. It will have a fixed height, but it should stretch dynamically to the full width of its container.

I couldn't think of a way to achieve this using purely CSS, so my next thought was to use SVG. This isn't very difficult to do with solid colors:

http://codepen.io/troywarr/pen/EPXVRV?editors=110

But, I'm stumped on how to apply a repeating background pattern to the SVG shape. It will need to line up with the background pattern in the <section>s above and below, and the background fill shouldn't scale with the dimensions of the shape, or it will appear distorted.

Applying some background images in CSS, I'm getting closer:

http://codepen.io/troywarr/pen/OMgyoE?editors=110

I just need the dark background pattern in the filled portion of the SVG.

Using a more visible image as a test, I'm able to stretch it to the dimensions of my <polyline>:

http://codepen.io/troywarr/pen/BjZoEq?editors=110

But, there's that stretching that I don't want. I need to tile my pattern, or at least not distort its native dimensions (so I can use a large swatch of it, if needed), even if the shape itself has a fluid width. I've tried several different combinations of attribute values for the <pattern> element, but I've yet to find anything that works as intended, even following some guidance from related answers:

Any suggestions? I'd love to hear any ideas for non-SVG approaches as well. Thanks!


UPDATE:

Sorry, I just realized that the background patterns in my CodePen examples weren't working. I've updated them with working image URLs.

Community
  • 1
  • 1
Bungle
  • 19,392
  • 24
  • 79
  • 106

3 Answers3

2

This is one way to do it with just CSS. You can use the after pseudo-elements to help you get those angles and just a single png for the diagonal(or an element rotated if you want to avoid the element) and another for the repeating pattern. Since I didn't have your images I just made some real fast, but this should more or less be what you want.

html { height:100%; }
body {
  padding:0;
  margin:0;
  height:100%;
  background:#333;
}

.demo {
  width:100%;
  height:auto;
  position:absolute;
}

body:after {
  position:absolute;
  content:'';
  top:0;
  bottom:0;
  right:0;
  left:0;
  pointer-events:none;
  background: transparent url(http://i.imgur.com/iUhGezx.png) repeat top left;
}

.demo .top {
  min-height:100px;
  background:#FFF;
  position:relative;
}

.demo .bottom { min-height:60px; }

.demo .top:after {
  position:absolute;
  content:'';
  top:100%;
  left:0;
  right:0;
  height:100px;
  background: transparent url(http://i.imgur.com/iEubBd5.png) repeat top left;  
  background-size: 100% 100px;
}
<div class="demo">
   <div class="top"></div>
   <div class="bottom"></div>
</div>
MiltoxBeyond
  • 2,683
  • 1
  • 13
  • 12
  • Thank you, MiltoxBeyond! The only limitation to this approach (and to web-tiki's) is that it relies on a single background image used for both sections. The pattern I'm using to replicate the design doesn't work over both the light and dark background colors. Please see my update to the original question (the CodePen examples should be fixed now); is there a way to use a separate background image above and below the diagonal split? – Bungle Jan 11 '16 at 19:15
  • 1
    Technically yes. You can use a background for the black element which would be below the diagonal split and a different background for the white section. The challenge is the white section. In that case you have a couple of options. Use an image with the background on it already. Another option is to use clip-path css property. (https://css-tricks.com/clipping-masking-css/) – MiltoxBeyond Jan 12 '16 at 20:38
2

Considering you need :

  • the slant width to be relative to viewport
  • a fixed height for the shape

There is a simple CSS approach you can use with border and viewport units :

body,html{padding:0;margin:0;}
div{
  border-bottom:50px solid rgba(0,0,0,.8);
  border-top: 50px solid transparent;
  background-image:url('http://i.imgur.com/iUhGezx.png');
}
div:before{
  content:'';
  display:block;
  border-right:100vw solid rgba(0,0,0,.8);
  border-top:50px solid transparent;
}
<div></div>

The pattern is repeated with the background-image property. The slant is made with the borders on the pseudo element.
The borders on the parent div are there just to make the top and bottom space around the slant.

Viewport related units (vw) are supported by IE9 and over (see canIuse for more info).


Update :

If you need to have a seperate background-image for both areas, there are 2 possible CSS approaches :

With transforms: supported by IE9 and over with vendor prefixes. The slant always has the same angle.

body,
html {
  padding: 0;
  margin: 0;
  overflow:hideden;
}
div{
  width:100%;height:150px;  
  position:absolute;
}
.top {
  padding-top:50px;
  background: #fff url('http://i.imgur.com/dzFT6wB.png');
}
.bot {
  transform-origin:100% 0;
  transform:rotate(-5deg);
  overflow:hidden;
  top:50px; right:0;
  width:110%;
}
.bot:after{
  content:'';
  position:absolute;
  right:0;top:0;
  width:100%;height:100%;
  transform-origin:inherit;
  transform:rotate(5deg) translatez(0px);
  background: #262729 url('http://i.imgur.com/LxTJ685.png');
}
<div class="top"></div>
<div class="bot"></div>

With the clip-path property: although it has low browser support, it will allow you to control the slant angle better :

body,html{padding:0;margin:0;}
div{
  position:relative;
  height:150px;
}
div:before, div:after{
  content:'';
  width:100%; height:100%;
  position:absolute;
}
div:before{
  background: url('http://i.imgur.com/dzFT6wB.png');
}
div:after{
  -webkit-clip-path:polygon(0% 60%, 100% 40%, 100% 100%, 0% 100%);
          clip-path:polygon(0% 60%, 100% 40%, 100% 100%, 0% 100%);
  background:#262729 url('http://i.imgur.com/LxTJ685.png');
}
<div></div>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • Thanks web-tiki! The only limitation to this approach (and to MiltoxBeyond's) is that it relies on a single background image used for both sections. The nature of the pattern I'm using to replicate the design doesn't work over both the light and dark background colors. Please see my update to the original question (the CodePen examples should be fixed now); is there a way to use a separate background image above and below the diagonal split? – Bungle Jan 11 '16 at 19:13
  • @Bungle I have updated my answer with 2 other possible approaches – web-tiki Jan 11 '16 at 20:01
  • 1
    Fantastic! Thanks so much for your help. I can live with the fixed slant angle in IE, and I'll use the clip-path approach where supported. It sounds like that's the best approach available right now. – Bungle Jan 12 '16 at 07:12
2

This is not currently possible with SVG. If you are stretching the SVG with preserveAspectRatio="none" then the entire contents of the SVG are affected. There is no way for some of the contents to opt out of the stretch transform.

In the future, there may be a way to do this in SVG2, but not with the current version of SVG.

Update

If you can live with it not working in IE, you can use a mask or a clip-path to achieve what you want. Below is an example of using clip-path.

body {
  margin: 0;
}

section {
  height: 50px;
}

main {
  background-image: url('http://mass-relevance-all-access.massrel.io/template-static-2e84fe3d1c7dc87710f58b990263ad6c29dacafc/img/bg-pattern-light.png');
}

.dark {
  background: #262729 url('http://mass-relevance-all-access.massrel.io/template-static-2e84fe3d1c7dc87710f58b990263ad6c29dacafc/img/bg-pattern-dark.png');
}

.diagonal {
  background: url(http://www.boogdesign.com/examples/svg/daisy-grass-repeating-background.jpg);
  -webkit-clip-path: url(#diagonalclip);
  clip-path: url(#diagonalclip);
}
<svg width="0" height="0">
  <defs>
    <clipPath id="diagonalclip" clipPathUnits="objectBoundingBox">
      <polyline points="0,1 1,0 1,1 0,1"/>
    </clipPath>
  </defs>
</svg>
<main>
  <section class="light"></section>
  <section class="diagonal"></section>
  <section class="dark"></section>
</main>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Thanks, Paul - that's what I feared. Are you aware of any way to do it without SVG? – Bungle Jan 11 '16 at 19:17
  • You can use a SVG `clip-path` to clip an HTML element that has the background. I've updated my answer with an example. – Paul LeBeau Jan 12 '16 at 05:45
  • Thanks again! I really appreciate your help and the code example - that makes sense. I ended up accepting web-tiki's answer because I'll need to rely on the CSS `transform` approach in most cases, given the current state of browser support. Hopefully Edge will support `clip-path` sometime this decade - looks like that's the only major outlier. http://caniuse.com/#feat=css-clip-path – Bungle Jan 12 '16 at 07:17