Hexagonal pattern with CSS - css

I found a great stackoverflow answer on how to create a hexagonal patten using CSS.
Generate repeating hexagonal pattern with CSS3
It's almost perfect, except i'd like to flip the hexagons the other way (ie. so the point is at the top). I've managed to do this fairly easily by swapping the main hex div width/height: (hexrow > div)... however i'm really struggling to re-align the background image on the other supporting divs. I've been trying to figure it out for a while now without much success.
Could anyone possibly post a jsFiddle that shows how it's done?
This is where i'm at currently: What i've tried
..and i believe this is what i need to amend:
.hexrow > div > div:first-of-type:before {
content: '';
position: absolute;
width: 200px; /* width of main + margin sizing */
height: 100%;
background-image: inherit;
background-position: 0 0;
background-repeat: no-repeat;
background-size: 120% auto;
bottom: 0;
left: 0;
z-index: 1;
-ms-transform:rotate(-60deg) translate(-150px, 0); /* IE 9 */
-moz-transform:rotate(-60deg) translate(-150px, 0); /* Firefox */
-webkit-transform:rotate(-60deg) translate(-150px, 0); /* Safari and Chrome */
-o-transform:rotate(-60deg) translate(-150px, 0); /* Opera */
transform:rotate(-60deg) translate(-150px, 0);
-ms-transform-origin: 0 0; /* IE 9 */
-webkit-transform-origin: 0 0; /* Safari and Chrome */
-moz-transform-origin: 0 0; /* Firefox */
-o-transform-origin: 0 0; /* Opera */
transform-origin: 0 0;
}
Any help much appreciated.

Use :nth-of-type(odd) and :nth-of-type(even) and set different margins for odd/ even hexagons on the same row.
Or you could do it in a much simpler manner, with less markup - check my answer at that question and this demo I just did. The idea is that you apply a series of transforms on the element (which has overflow: hidden) in order to get a rhombus with an acute angle of 60 degrees and then you undo all those transforms in reverse order for a pseudo-element or a child element if you wish (having the same height as the element itself, but only .866 of its width, because .866 is the ratio of the distance between two parallel sides of a hexagon and its big diagonal) on which you actually apply the background-image. So there's no chance of misalignment, because the background image is only applied on one element.
Basic HTML structure:
<div class='row'>
<div class='hexagon'></div>
</div>
<div class='row'>
<div class='hexagon content ribbon' data-content='This is a test!!!
9/10'></div><!--
--><div class='hexagon content longtext' data-content='Some longer text here.
Bla bla bla bla bla bla bla bla bla bla blaaaah...'></div>
</div>
Relevant CSS:
.row { margin: -8% 0%; text-align: center; }
.row:first-child { margin-top: 2.25%; }
.hexagon {
position: relative;
display: inline-block;
overflow: hidden;
margin: 0 -1.5%;
padding: 16%;
transform: rotate(-30deg) skewX(30deg) scaleY(.866); /* .866 = sqrt(3)/2 */
}
.hexagon:before {
display: block;
position: absolute; /* 86.6% = (sqrt(3)/2)*100% = .866*100% */
right: 6.7%; bottom: 0; left: 6.7%; top: 0; /* 6.7% = (100% -86.6%)/2 */
transform: scaleY(1.155) skewX(-30deg) rotate(30deg); /* 1.155 = 2/sqrt(3) */
background-color: rgba(30,144,255,.56);
background-size: cover;
content: '';
}
.row:first-child .hexagon:first-child:before {
background-image: url(img.jpg);
}
/* and so on, add background images for all hexagons */

I used borders.
Codepen.io
<div id="hex"></div>
And
#hex {
display: inline-block;
position: relative;
width: 190px;
height: 220px;
background: no-repeat url("http://placekitten.com/200/300") 50% 50%;
}
div:before {
content: " ";
display: block;
border-top: 0px solid transparent;
border-bottom: 55px solid transparent;
order-left: 95px solid white;
border-right: 95px solid white;
}
div:after {
content: " ";
display: block;
border-left: 95px solid white;
border-top: 55px solid transparent;
border-right: 95px solid white;
margin-top:110px
}

Related

Produce a rectangle shaped box with a heavy straight right arrow in CSS

I am trying to produce a rectangle connected to a heavy-arrow (right facing) like the following:
(Link to image for those using SO dark theme)
I have attempted this by splitting the shape into parts. I have attempted drawing the rectangle first (and placing it in the same class as the arrow holder) then drawing the base of the arrow. Finally, the head by using rotation and transparency. In my current version of the CSS code can't seem to move the arrow head outside the rectangle to resemble the one shown in the image above. I have been trying to achieve this by tweaking the parameters and trying different CSS properties. Please suggest solutions and approaches.
body {
height: 100%;
width: 100%;
background-color: black;
overflow: hidden;
}
/* Arrow holder */
.arrowed {
position: relative;
height: 200px;
width: 200px;
margin: 0 20px 20px 0;
border: 1px solid rgba(0, 0, 0, 0.25);
}
.arrowed div {
float: right;
top: 0;
bottom: 0;
left: 18;
right: 0;
margin: auto;
}
.arrow-5 {
/* more triangle */
position: relative;
height: 22px;
width: 35px;
border: 30px solid;
border-color: white white transparent transparent;
transform: rotate(45deg);
}
.arrow-5:before {
content: '';
position: absolute;
top: 0px;
right: 0px;
display: block;
height: 54px;
width: 58px;
background-color: white;
transform: rotate(-45deg) translate(10px, 1px);
}
.rectangle {
width: 200px;
height: 100px;
background: blue;
}
<div class="arrowed rectangle">
<div class="arrow-5"></div>
</div>
You can draw block with arrow on the right by using pseudo elements.
In this example I'm using CSS variables to easelly control sizes and gaps. If it's impossible to use for some reason, you can replace it manually and use this Code Snippet like an generator.
This approach also support shadows, if needed.
/* root variables */
:root {
--space: 1rem;
--bg-color: #47baffb3;
}
/* main block bg color and part between of block and arrow */
.arrow-block,
.arrow-block:before {
background-color: var(--bg-color);
}
/* arrow block (text container) */
.arrow-block {
position: relative;
padding: var(--space);
margin-right: calc(var(--space) * 3);
filter: drop-shadow(0 0 .5rem rgba(0, 0, 0, .6));
}
/* arrow parts */
.arrow-block:before,
.arrow-block:after {
content: '';
position: absolute;
top: 50%;
transform: translate3d(0, -50%, 0);
}
/* part between block and arrow */
.arrow-block:before {
height: calc(var(--space) * 2);
width: var(--space);
right: calc(var(--space) * -1);
}
/* arrow itself */
.arrow-block:after {
--arrow-side-size: calc(var(--space) * 2);
border-bottom: var(--arrow-side-size) solid transparent;
border-top: var(--arrow-side-size) solid transparent;
border-left: var(--arrow-side-size) solid var(--bg-color);
right: calc(var(--space) * -3);
}
<div class="arrow-block">
<p>Block with arrow</p>
<p>Block with arrow second line</p>
</div>

Partial color in bottom border to show progress bar

Is there a way to use a linear-gradient to set a two-color bottom border so that it can be used as a progress bar? Think about the way Safari shows you the progress bar for when a website is loading.
We can do it using background:
background-image: linear-gradient(90deg, green 10%, red 0%, red 100%);
This would generate a div that's 10% green and 90% red. Can a similar technique be used on the bottom border of the div? Also, can the width of this bottom border be controlled so that it's 3px?
I would rather create an element for it, but you can do something like this:
Please don't use green and red due to color blindness issues.
body {
margin: 0;
padding: 0;
}
header {
--progress: 10%;
background-color: khaki;
height: 3rem;
border-bottom: 3px solid;
border-image: linear-gradient(90deg, green var(--progress), red 0%, red 100%) 1;
}
<header></header>
[EDIT] I can add how I would set up a progress bar with pseudo-elements. I would prefer using two (one as a background; another as progress), so it's easier to animate the progress.
Added a range input to make it a little bit more interactive.
let headerElements = document.querySelectorAll('header');
function updateHeaders(value) {
headerElements.forEach((header) => {
header.style.setProperty('--progress', value + "%");
});
}
body {
--primary-color: lightblue;
margin: 0;
padding: 0;
}
header {
--progress: 30%;
background-color: var(--primary-color);
display: flex;
align-items: center;
/* RELEVANT CSS */
position: relative;
}
/* RELEVANT CSS */
header.progressbar::before,
header.two.pseudo-elements.progressbar::after {
content: '';
position: absolute;
bottom: 0px;
left: 0px;
right: 0px;
height: 3px;
}
header.one.pseudo-element.progressbar::before {
background-image: linear-gradient(90deg, green var(--progress), red 0%, red 100%);
}
header.two.pseudo-elements.progressbar::before {
z-index: 2;
right: initial;
width: var(--progress);
background-color: green;
transition: width 300ms linear;
}
header.two.pseudo-elements.progressbar::after {
z-index: 1;
background-color: red;
}
/* PLACEHOLDER CSS BELOW */
input[type="range"] {
margin: 1rem 0px;
width: 100%;
}
div[title="Logotype"] {
width: 35px;
height: 35px;
display: flex;
justify-content: center;
align-items: center;
font-family: "Verdana";
font-size: 36px;
padding: 0.25rem;
margin: 0.5rem;
background-color: white;
border-radius: 50%;
}
header > a {
padding: 0px 0.5rem;
color: #121212;
}
<h3>One pseudo-element</h3>
<header class="one pseudo-element progressbar">
<div title="Logotype">L</div>
Link 1
Link 2
</header>
<h3>Two pseudo-elements</h3>
<header class="two pseudo-elements animate progressbar">
<div title="Logotype">L</div>
Link 1
Link 2
</header>
<input type="range" oninput="updateHeaders(this.value)" value="30" />

How does transform-origin work with scale and transition? [duplicate]

When we use CSS3 transform: operation1(...) operation2(...), which one is done first?
The first operation done seems to be the one the most on the right., i.e. here operation2 is done before operation1. Just to be sure, is it true?
Note: I have read one thing and its contrary in some places (answers, articles on the internet), thus the question here.
Yes, the first operation done is the one the most on the right., i.e. here operation2 is done before operation1.
This MDN article states indeed:
The transform functions are multiplied in order from left to right, meaning that composite transforms are effectively applied in order from right to left.
Here is the documentation : http://www.w3.org/TR/css-transforms-1/.
Example 1
Here the scaling is done first, and then the translation of 100px vertically (if translation was done first, the scaling would make the translation of 500px!)
#container {
position: absolute;
transform: translate(0,100px) scale(5);
transform-origin: 0 0; }
<div id="container"><img src="https://i.stack.imgur.com/xb47Y.jpg"></img></div>
Example 2
Here the translation is done first, and then the scaling (the scaling done after makes that the translation looks like a 500px-translation!)
#container {
position: absolute;
transform: scale(5) translate(0,100px);
transform-origin: 0 0; }
<div id="container"><img src="https://i.stack.imgur.com/xb47Y.jpg"></img></div>
This has been mentioned in other answers and comments, but not with enough emphasis in my opinion: the short answer is both ways are valid.
It all depends whether you consider your coordinates attached to your element (left to right) or fixed to the page based on the initial element position (right to left).
Here is an article showing the difference with animations (which makes it easier to understand): Chaining transforms.
Here is a snippet showing the animations from the article:
html, body { height: 100%; }
body {
background: #aaa;
color: #000;
font-family: Calibri,Candara,Segoe,"Segoe UI",Optima,Arial,sans-serif;
overflow: hidden;
margin: 0;
}
.info {
text-align: center;
font-family: Consolas,monaco,monospace;
font-size: 20px;
font-weight: bold;
margin-bottom: 4px;
color: #fff;
}
.split { white-space: nowrap; }
.side {
display: inline-block;
width: 50%;
}
.label {
text-align: center;
font-size: 20px;
}
.container {
position: relative;
font-size: 50px;
margin: .6em auto 0;
width: 0; height: 0;
transform: translateX(-1em);
}
.ltr .object {
position: absolute;
left: 0; top: 0;
width: 1em; height: 1em;
margin: -.5em 0 0 -.5em;
background: rgb(114,34,34);
animation: ltrObj 5s infinite;
}
#keyframes ltrObj {
from, 10% { transform: rotate( 0deg) translateX(0em); }
40% { transform: rotate(45deg) translateX(0em); }
70%, to { transform: rotate(45deg) translateX(2em); }
}
.object.shadow {
animation: none;
opacity: .2;
}
.ltr .axes {
position: absolute;
left: .5em; top: .5em;
width: 1em; height: 1em;
color: #111;
box-sizing: border-box;
border-left: 2px solid;
border-top: 2px solid;
}
.ltr .axes::before, .ltr .axes::after {
content: '';
position: absolute;
width: .2em; height: .2em;
box-sizing: border-box;
border-left: 2px solid;
border-top: 2px solid;
transform-origin: top left;
}
.ltr .axes::before { top: 100%; left: 0; margin-left: -1px; margin-top: 1px; transform: rotate(225deg); }
.ltr .axes::after { top: 0; left: 100%; margin-top: -1px; margin-left: 1px; transform: rotate(135deg); }
.rtl .axes {
position: absolute;
left: 0; top: 0;
width: 2.5em; height: 2.3em;
color: #111;
box-sizing: border-box;
border-left: 2px solid;
border-top: 2px solid;
}
.rtl .axes::before, .rtl .axes::after {
content: '';
position: absolute;
width: .2em; height: .2em;
box-sizing: border-box;
border-left: 2px solid;
border-top: 2px solid;
transform-origin: top left;
}
.rtl .axes::before { top: 100%; left: 0; margin-left: -1px; margin-top: 1px; transform: rotate(225deg); }
.rtl .axes::after { top: 0; left: 100%; margin-top: -1px; margin-left: 1px; transform: rotate(135deg); }
.rtl .object {
position: absolute;
left: 0; top: 0;
width: 1em; height: 1em;
margin: -.5em 0 0 -.5em;
background: rgba(100,0,0,0.8);
animation: rtlObj 5s infinite;
}
#keyframes rtlObj {
from, 10% { transform: rotate( 0deg) translateX(0em); }
40% { transform: rotate( 0deg) translateX(2em); }
70%, to { transform: rotate(45deg) translateX(2em); }
}
.helper-mask {
position: absolute;
left: 0; top: 0;
width: 3em; height: 3em;
overflow: hidden;
}
.helper {
position: absolute;
left: 0; top: -2em;
width: 0; height: 2em;
margin-top: 2px;
box-sizing: border-box;
border: 2px solid #00c;
border-left: none;
border-radius: 0 100% 0 0;
transform-origin: bottom left;
animation: helper 5s infinite;
}
#keyframes helper {
from, 10% { width: 0em; transform: rotate( 0deg); }
40% { width: 2em; transform: rotate( 0deg);}
70%, to { width: 2em; transform: rotate(45deg);}
}
<div class="info">rotate(45deg) translateX(2em)</div>
<div class="split">
<div class="side ltr">
<div class="label">Left to Right</div>
<div class="container">
<div class="object shadow"></div>
<div class="object">
<div class="axes"></div>
</div>
</div>
</div>
<div class="side rtl">
<div class="label">Right to Left</div>
<div class="container">
<div class="axes"></div>
<div class="object"></div>
<div class="helper-mask">
<div class="helper"></div>
</div>
</div>
</div>
</div>
Whether the actual implementation uses left to right or right to left is irrelevant, both are equally valid when creating an animation, as long as you keep the difference in mind.
Transforms are performed left to right. Transforms correspond to matrix operations, and these are performed left to right.
There is intuition behind it, it's not just that this is literally in the spec as a normative rule (point 3 here: https://drafts.csswg.org/css-transforms-1/#transform-rendering)
Here's a pen to try: https://codepen.io/monfera/pen/YLWGrM
Explanation:
Each transform step establishes its own coordinate system. So
transform: translateX(500px);
establishes a new coordinate system 500px along the X axis of its parent, and the element will be rendered there.
Similarly,
background-color: blue;
transform: translateX(500px) rotate(60deg);
first establishes a new coordinate system 500px along the X axis (to the right) of its parent, and only then, within that (translated, but it's now irrelevant) coordinate system does it perform the rotation. So it'll be a shape that's 500px to the right, and rotated in place (around the so-called transform-origin which is interpreted in the local coordinate system, and the default 50% 50% for rotation means, rotation around the center of the rectangle, but it's an aside).
The reverse order
background-color: orange;
transform: rotate(60deg) translateX(500px);
first establishes a new coordinate system that's rotated 60 degrees relative to the parent, and then translates 100px along the X axis of the now rotated coordinate system, in a direction that is not actually to the right from the global viewpoint of the document (or user). So, in this case, it's as if you first rotated the paper, and then slid the shape 500 units along the side of the paper (from the origin, which is in this case the top left corner).
For a more advanced discussion, and understanding of how it's possible to intuitively understand it for both directions, check out Composing Transformations - CSS transforms follow the post-multiplication model, so look for the page with the heading "Think of transformations as transforming the local coordinate frame" (illustrations seem to be a little off though)
It applies the leftmost transformation first.
As you can see in the image above, the first transformation takes a longer distance as compared to the second. The reason is the first example undergoes scale first and then it takes the distance specified by translate based on its new width on the x-axis. Because it is wider now, 50% will cause it to take a longer distance. The measure specified by 50% is calculated by taking half of the width of itself.
the site I cited from
I just created a demo of a 3d room in HTML using CSS transforms. I made a 200x200 DIV for a back wall, leaving it in that position. Then I made a left wall starting in the same size and position, then added
transform: translate3d(-100px,0px,100px) rotateY(90deg).
Then I made a right wall and added
transform: translate3d( 100px,0px,100px) rotateY(90deg).
This created the room correctly. But this is with version 13 of Safari. Originally I tried to list the rotation step first, but the wall was in an odd position. So I'm seeing a right-to-left behavior.

Is it possible to create this irregular quadrilateral with CSS?

I've tried the perspective solution here How to transform each side of a shape separately? but can't get it to work probably due to the irregularness of the shape. Only the top and right side columns are slanted, vertical and bottom are straight. How can I do this with CSS?
Using CSS borders you can create triangles and trapezoids.
You can achieve your shape joining a triangle and a trapezoid.
.triangle {
border: 0 solid red;
border-left-width: 500px;
border-top-width: 30px;
border-top-color: transparent;
}
.trapezoid {
border: 0 solid red;
width: 500px;
border-bottom-width: 150px;
border-right-width: 30px;
border-right-color: transparent;
}
<div class="triangle"></div>
<div class="trapezoid"></div>
Method 1: Clip path
You could make use of CSS clip-path feature to clip a rectangle into the required polygon shape.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
background: red;
padding: 10px;
-webkit-clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<div>Some text</div>
<div id="image"></div>
Pros:
Supports non-solid color fills inside the shape and also allow text to be present inside.
The shape is responsive and can adapt even if the container's dimensions change.
Cons:
Poor browser support for the CSS clip-path feature. This can be overcome by using inline SVG for the clip-path like in the below snippet as this has much better browser support.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
padding: 10px;
background: red;
-webkit-clip-path: url(#clip);
clip-path: url(#clip);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<svg width="0" height="0">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="M0 0, 0.9 0.1, 1 1, 0 1z" />
</clipPath>
</defs>
</svg>
<div>
Some text
</div>
<div id="image"></div>
Method 2: CSS Transforms
Generally it is better not to use transforms when there is going to be content like image or text inside the shape (or) when the shape's background is not going to be a solid color because then we would either have to (a) reverse transform the child elements separately to make them look normal or (b) use absolute positioning.
For this particular shape, having text inside the shape is not a problem even while using transforms but having non solid background colors would be.
Option 1: Using two pseudo-elements
You could use a couple of pseudo-elements with skew transforms, position one on the top and the other on the right to produce the required shape. Hover the shape in snippet to see how it is created.
div {
position: relative;
height: 150px;
width: 250px;
background: red;
margin: 40px 40px 0px 0px;
}
div:after,
div:before {
position: absolute;
content: '';
background: red;
z-index: -1;
backface-visibility: hidden;
}
div:before {
height: 12.5%;
width: 100%;
top: 0px;
left: 0px;
transform-origin: right top;
transform: skewY(3deg);
}
div:after {
height: 100%;
width: 12.5%;
right: -1px;
top: -1px;
transform-origin: right top;
transform: skewX(10deg);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 300px;
}
div:hover:after{
background: blue;
}
div:hover:before{
background: green;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Cons:
Having gradients (or) images as background for the shape is complex because they would need reverse rotation as mentioned earlier.
Shape is not 100% scalable as dimensions of the container should change proportionately for the shape to be maintained (hover on the shape in the snippet to see what I mean). Reason is same as mentioned here.
Option 2: Using one pseudo-element
This is pretty similar to the previous option except that this uses a single pseudo-element along with a overflow: hidden on the parent.
div {
position: relative;
box-sizing: border-box;
height: 200px;
width: 300px;
padding: 10px;
overflow: hidden;
}
div:after {
position: absolute;
content: '';
top: 0px;
left: -20px;
height: 100%;
width: 100%;
background: red;
transform-origin: left bottom;
transform: skewY(5deg) skewX(7.5deg);
z-index: -1;
}
div:hover {
height: 300px;
width: 500px;
transition: all 1s;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Shape is responsive and can adapt even if the container's dimensions change .
Cons:
Same constraint as the previous option for gradient and image backgrounds.
Not suitable if the overflow: hidden on the parent is a constraint.
A solution is:
div {
width: 300px;
height: 100px;
margin:50px;
background-color: yellow;
border: 1px solid black;
}
.thisdiv {
-ms-transform: skewX(-20deg); /* IE 9 */
-webkit-transform: skewX(-20deg); /* Safari */
transform: skewX(-20deg); /* Standard syntax */
}
<div class="thisdiv">
This is the div I will skew
</div>
This is how to skew an element, if you want to make the shape you added, try using two overlaping div's, position, scale, rotate and skew, like this:
.outer-div{
position:relative;
margin:50px;
width:200px;
height:200px;
border:2px black dashed;
}
.inner-one{
position:absolute;
left:0;
bottom:0;
width:180px;
height:180px;
background:red;
}
.inner-two{
position:absolute;
bottom:2px;
right:0px;
width:200px;
height:195px;
background:red;
transform: rotate(7deg) skew(14deg) scale(0.905); /* Standard syntax */
}
<div class="outer-div">
<div class="inner-one">
</div>
<div class="inner-two">
</div>
</div>
2 Triangle Solution for Irregular Quadrilateral in CSS
In looking at your image, I notice that the skew at the top and right are really just long, narrow triangles overlaying the rectangle.
So what I did was create triangles using CSS border properties and absolutely position them over the rectangle.
#rectangle {
width: 400px;
height: 200px;
background-color: red;
margin-top: 25px;
position: relative;
}
#triangle-down {
border-left: 30px solid red;
border-right: 0;
border-top: 200px solid transparent;
position: absolute;
right: -30px;
top: 0;
}
#triangle-left {
border-top: 0;
border-bottom: 15px solid red;
border-right: 400px solid transparent;
position: absolute;
right: 0;
top: -15px;
}
<div id="rectangle">
<div id="triangle-down"></div>
<div id="triangle-left"></div>
</div>
jsFiddle demo
You could check out the clip-path property (see below from MDN), but support is very patchy. Chrome 24+ supports with prefix and FF, but only URL values, which reference a path in an SVG. You can read more about clip-path here.
Here's a basic pen - this will only work in Chrome.
From MDN
The clip-path CSS property prevents a portion of an element from getting displayed by defining a clipping region to be displayed i.e, only a specific region of the element is displayed. The clipping region is a path specified as a URL referencing an inline or external SVG, or shape method such as circle(). The clip-path property replaces the now deprecated clip property.
developer.mozilla.org/en-US/docs/Web/CSS/clip-path (sorry, not enough rep to link)

Positioning and resizing a CSS split-colored triangle to desired position and proportions

Through help on stackoverflow I've been able to generate and position a CSS triangle in the correct position on my website, I've also learnt how to color a triangle in 2 equal halves.
But I am stuck on merging the two examples together, what I've tried I don't think is worth pasting here due to the mess I've made of it.
I am trying to get a triangle that has the proportions and sits at the bottom of the div like this fiddle example and then is split in 2 colors like this fiddle example.
Where I believe I am going wrong is that in the different fiddles there are different uses of:
:before
Well..., Here is my attempt to achieve this effect (proportions + split in 2 colors):
JSFiddle Demo.
In this demo, I added the triangle to the .bottom div and positioned that to stay at the top (with a negative value).
Then added margin-top: 1%; property to move the triangle when resizing the window:
HTML
<div class="top"></div>
<div class="bottom">
<div class="triangle"></div>
</div>
CSS:
.top {
/* other styles... */
position: relative;
z-index: 2;
}
.bottom {
background: lightGreen;
height: 100px;
position: relative;
z-index: 1; /* A lower z-index value than .top */
/* Or use overflow: hidden; instead */
}
.triangle {
width: 40px;
height: 20px;
position: absolute;
left: 0;
right: 0;
top: -20px;
margin: auto;
margin-top: 1%; /* Move the triangle when resizing the window */
z-index: 1;
}
.triangle:before {
content: " ";
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 0 20px 20px 0;
border-color: transparent blue transparent transparent;
}
.triangle:after {
content: " ";
position: absolute;
left: 20px;
width: 0;
height: 0;
border-style: solid;
border-width: 20px 20px 0 0;
border-color: red transparent transparent transparent;
}

Resources