Overlapping triangles - css

Here is the shape I'm trying to create in pure CSS:
I have a more complete jsfiddle http://jsfiddle.net/8Lxr5s57/7/. Is there a better, more efficient way to achieve this same result?
.angled_container {
background-color: #fff;
height: 200px;
position: relative;
overflow: hidden;
clear: both;
}
.angled_container:before,
.angled_container:after {
content: "";
width: 110%;
height: 100%;
display: block;
position: absolute;
top: 0;
}
.angled_container:before {
background-color: #606060;
transform: rotate(12deg);
-webkit-transform-origin: left top;
left: 0;
}
.angled_container:after {
background-color: #6bb2c6;
transform: rotate(-12deg);
-webkit-transform-origin: right top;
left: -10%;
}
.angled_container--open-left:before {
background-color: #6bb2c6;
z-index: 2;
}
.angled_container--open-left:after {
background-color: #606060;
z-index: 1;
}
<div class="angled_container angled_container--open-right"></div>

CSS
I would suggest using skewY() instead of rotate() for the two triangles. it will avoid some positioning issues and prevent using wider pseudo elements than the container :
.angled_container {
height: 200px;
position: relative;
overflow: hidden;
}
.angled_container:before,
.angled_container:after {
content: "";
width: 100%; height: 100%;
display: block;
position: absolute;
top: 0; left: 0;
}
.angled_container:before {
background-color: #606060;
transform: skewY(12deg);
transform-origin: left top;
}
.angled_container:after {
background-color: #6bb2c6;
transform: skewY(-12deg);
transform-origin: right top;
}
<div class="angled_container angled_container--open-right"></div>
SVG
Alternatively, you can use an inline SVG with 2 polygon elements. This is totaly responsive and probably easier to make/maintain as you can style the triangles in CSS with the fill property :
svg{display:block; width:100%;}
.first{
fill:#606060;
}
.second{
fill:#6bb2c6;
}
<svg viewbox="0 0 100 30">
<polygon class="first" points="0 0 100 28 0 25 0 28"/>
<polygon class="second" points="0 28 0 25 100 0 100 28 52 28 50 30 48 28 0"/>
</svg>

Break them down into triangles. This supports IE8+.
.container {
position: relative;
width: 1000px;
height: 260px;
border-bottom: 40px solid #65abc2;
}
.grey {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border-bottom: 260px solid #595959;
border-right: 1000px solid transparent;
}
.blue {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border-bottom: 260px solid #65abc2;
border-left: 1000px solid transparent;
}
.container:after {
content: '';
display: block;
position: absolute;
bottom: -53px;
/* included thickness of border-bottom */
left: 50%;
margin-left: -17px;
width: 0px;
height: 0px;
border-top: 13px solid #65abc2;
border-left: 17px solid transparent;
border-right: 17px solid transparent;
}
<div class="container">
<div class="grey"></div>
<div class="blue"></div>
</div>

You can do it all with CSS triangles but I'm not sure its any better than what you have already. You'll need the pseudo elements ::before and ::after to get the extra space at the bottom and the mini arrow.
div {
width:0;
height:0;
margin-top:55px;
border-top:130px solid white;
border-right:500px solid #6DB1C3;
border-bottom:140px solid #6DB1C3;
border-left:500px solid #5F5F5F;
position:relative;
}
div:before {
content:" ";
position:absolute;
bottom:-170px;
width:1000px;
height:30px;
left:-500px;
background:#6DB1C3;
}
div:after {
content:" ";
position:absolute;
bottom:-202px;
left:-20px;
width:0;
height:0;
border:20px solid transparent;
border-top:12px solid #6DB1C3;
}
<div></div>

Related

How to implement a Spread out edge in CSS [duplicate]

I have CSS code
#box {
width: 200px;
height: 50px;
background-color: blue;
border-top-left-radius: 9999px;
border-bottom-left-radius: 9999px;
position: relative;
margin: 30px;
text-align: center;
color: white;
padding-top: 10px;
}
#box::before,
#box::after {
content: "";
width: 0;
height: 0;
right: 0;
position: absolute;
}
#box::before {
border-right: 10px solid blue;
border-top: 10px solid blue;
border-left: 10px solid transparent;
border-bottom: 10px solid transparent;
bottom: -20px;
}
#box::after {
border-right: 10px solid blue;
border-top: 10px solid transparent;
border-left: 10px solid transparent;
border-bottom: 10px solid blue;
position: absolute;
top: -20px;
}
<div id="box">#box</div>
which gives some shape like
shape I need is
I need curved line instead of hypotenuse in triangles at top-right (#box::before) and bottom-right (#box::after) as in image.
Is there any way to achieve using pure CSS ?
codesandbox demo
Thanks
You can create a concaved radius using the box-shadow property.
This technique creates a transparant square with overflow hidden.
It then creates a transparant circle with a box shadow.
We then adjust the position of the circle to only view 1 quarter of
it.
SNIPPET
#box {
position: relative;
width: 200px;
height: 50px;
background-color: blue;
border-radius: 9999px 0 0 9999px;
margin: 30px;
text-align: center;
color: #fff;
padding-top: 10px;
}
#top,
#bottom {
position: absolute;
height: 30px;
width: 30px;
right: 0;
overflow: hidden;
}
#top {
top: -30px;
}
#bottom {
bottom: -30px;
}
#top::before,
#bottom::before {
content: '';
position: absolute;
right: 0;
height: 200%;
width: 200%;
border-radius: 100%;
box-shadow: 10px 10px 5px 100px blue;
z-index: -1;
}
#top::before {
top: -100%;
}
<div id="box">
<div id="top"></div>
#box
<div id="bottom"></div>
</div>
You can easily achieve this by using svg background images like in this snippet. Here the curves may not the way you want but surely you can change the path in the svg to your needs.
#box {
width: 200px;
height: 50px;
background-color: blue;
border-top-left-radius: 9999px;
border-bottom-left-radius: 9999px;
position: relative;
margin: 30px;
}
#box::before,
#box::after {
content: "";
width: 20px;
height: 20px;
right: 0;
position: absolute;
}
#box::before {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><path fill="blue" d="M0 0 Q20 0 20 20 L20 0Z" /></svg>');
bottom: -20px;
}
#box::after {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><path fill="blue" d="M0 20 Q20 20 20 0 L20 20Z" /></svg>');
top: -20px;
}
<div id="box"></div>
Can you use negative space? You could have a container with the same background color as your shape, then round the corners surrounding elements to create the illusion.
.container {
background-color: blue;
width: 100%;
}
.negat {
background-color: white;
height: 100px;
}
.posit-bg {
background-color: white;
}
.posit {
background-color: blue;
height: 100px;
border-radius: 50px 0px 0px 50px;
}
.top {
border-radius: 0px 0px 50px 0px;
}
.bot {
border-radius: 0px 50px 0px 0px;
}
<div class="container">
<div class="negat top"></div>
<div class="posit-bg">
<div class="posit"></div>
</div>
<div class="negat bot"></div>
</div>
#box{
width:200px;
height:50px;
background-color:blue;
color:#ffffff;
text-align:center;
padding-top:30px;
border-radius:9999px 0 0 9999px;
}
.sq{
width:25px;
height:25px;
background-color:blue;
}
#sq1,#sq2,#sq11,#sq22{
border-radius:-999px;
margin-left:175px;
}
.sq1{
background-color:#ffffff;
height:25px;
width:25px;
}
#sq11{
border-bottom-right-radius:9999px;
margin-bottom:-25px;
position: relative;
z-index:1;
}
#sq22{
border-top-right-radius:9999px;
margin-top:-25px;
position: relative;
z-index:1;
}
<div class="sq1" id="sq11"></div>
<div class="sq" id="sq1"></div>
<div id="box">#box</div>
<div class="sq" id="sq2"></div>
<div class="sq1" id="sq22"></div>

Slanted box shadow on left and right side

I am trying to make slanted box shadow on both sides of a div, which I have added here as an image.
The red part is indicating here shadow. actually color is not solid, it should gradually decrease when it is moving to outside from border.
Here is my contribution hope it gives you a baseline.
.box {
width: 150px;
height: 200px;
position: relative;
padding-left: 25px;
padding-right: 25px;
}
.box-content {
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
background-color: white;
border: 2px solid black;
width: 100%;
height: 100%;
position: relative;
}
.box::before {
content: '';
display: block;
border-top: 0;
border-bottom: 180px solid transparent;
border-right: 25px solid red;
position: absolute;
left: 0;
bottom: 0;
}
.box::after {
content: '';
display: block;
border-top: 0;
border-bottom: 180px solid transparent;
border-left: 25px solid red;
position: absolute;
right: -4px;
bottom: 0;
}
<div class="box">
<div class="box-content">
Box
</div>
</div>
Try this:
div{
width: 200px;
height: 200px;
border:1px solid black;
background: white;
}
div:before{
content:' ';
display:block;
width: 200px;
height:200px;
background: linear-gradient(transparent, black);
position: fixed;
transform: matrix3d(1.1,0,0.00,0,0.00,0.71,0.71,0.0007,0,-0.71,0.71,0,0,37,0,1); z-index: -1;
}
<div>Hello</div>
Using transform: skew() applied to the div's before and after
jsFiddle 1
code:
#test {
width: 150px;
height: 220px;
line-height: 220px;
background-color: white;
border: 2px black solid;
text-align: center;
position: relative;
margin: 10px 150px;
}
#test:before, #test:after {
width: 150px;
height: 200px;
position: absolute;
bottom: 0;
left: -11px;
z-index: -1;
content: " ";
display: block;
background-color: red;
transform: skew(5deg, 0);
}
#test:after {
transform: skew(-5deg, 0);
left: 11px;
}
<div id="test">Box</div>
EDIT : to give the shadow effect some real blur with gradient and transparency, we could make use of linear-gradient background with two rgba() values, as well as CSS blur() (1) filter.
jsFiddle 2
code:
#test {
width: 150px;
height: 220px;
line-height: 220px;
background-color: white;
border: 2px black solid;
text-align: center;
position: relative;
margin: 10px 150px;
}
#test:before, #test:after {
width: 150px;
height: 200px;
position: absolute;
bottom: 0;
left: -11px;
z-index: -1;
content: " ";
display: block;
background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.7));
transform: skew(5deg, 0);
filter: blur(2px);
}
#test:after {
transform: skew(-5deg, 0);
left: 11px;
}
<div id="test">Box</div>
Notes:
(1) browser support for CSS filter

Irregular Div shape Distort one corner only

How would i create a div shape like this? I have read a lot of techniques but i could not figure this one out. Inside the div is text that should not be distorted.
Every technique is welcome it does not have to be pure css.
My HTML structure:
<div class="intro">
<div class="intro-header">
<h1>Headline WOW</h1>
</div>
<div class="intro-text">
<p>Mieleni minun tekevi, aivoni ajattelevi lähteäni laulamahan, saa'ani sanelemasaa'ani sanelema sanelemasaa'ani sanelema </p>
</div>
</div>
you could use some skewed pseudo elements for this:
.first,
.last {
text-align: center;
line-height: 80px;
height: 80px;
background: green;
position: relative;
display: inline-block;
width: 400px;
margin-bottom: 20px;
}
.first:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
height: 50%;
width: 100%;
transform: SkewY(2deg);
transform-origin: bottom left;
background: inherit;
}
.last:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 50%;
width: 100%;
transform: SkewY(2deg);
transform-origin: bottom right;
background: inherit;
}
<div class="first">FIRST LINE</div>
<div class="last">LAST LINE</div>
An alternative (possibly) would be to use a gradient (although this may lead to jagged edges). Solution credit to Harry
body {
background: -webkit-linear-gradient(0deg, crimson, indianred, purple);
}
div {
height: 400px;
width: 400px;
background: -webkit-linear-gradient(75deg, lightseagreen 45%, transparent 45%, transparent 55%, lightseagreen 55%);
}
<div></div>
You can do this with border cut-offs.
As an example:
.top {
height: 300px;
background: red;
position: relative;
width: 300px
}
.top:before {
content: '';
position: absolute;
bottom: 0;
right: 0;
border-bottom: 10px solid white;
border-right: 300px solid red;
width: 0;
}
.bottom {
height: 300px;
background: red;
position: relative;
width: 300px;
padding-top: 10px;
margin-top: 0px;
}
.bottom:before {
content: '';
position: absolute;
top: 0;
right: 0;
border-top: 10px solid white;
border-left: 300px solid red;
width: 0;
}
<div class="top">Text</div>
<div class="bottom">Text</div>
This should do it.
html,body{
margin:0;
height:100%;
}
.intro{
width:400px;
display:inline-block;
background:red;
padding:50px;
}
.intro-header,.intro-text{
width:100%;
display:inline-block;
background:#ccc;
text-align:center;
position:relative;
}
.intro-header{
margin-bottom:50px;
}
.intro-header:after{
position:absolute;
left:0;
content:"";
width: 0;
height: 0;
border-left: 400px solid transparent;
border-top: 20px solid #ccc;
}
.intro-text:after{
position:absolute;
top:-20px;
left:0;
content:"";
width: 0;
height: 0;
border-right: 400px solid transparent;
border-bottom: 20px solid #ccc;
}
Example: CodePen

CSS to create an acute isosceles triangle with curved edges

I am trying to create a triangle using purely CSS which has curved edges.
Is this possible without it being totally over the top?
I've added an example below of what I'm trying to achieve (the curved lines - not the straight lines).
So far I have been working with the following code but it's not quite what I'm looking for.
#inner {
transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-o-transform: rotate(45deg);
-moz-transform: rotate(45deg);
background-color: silver;
width: 100px;
height: 100px;
top: 20px;
left: -50px;
position: relative;
-moz-border-radius: 20px;
border-radius: 20px;
}
#outer {
position: absolute;
width: 70px;
height: 140px;
top: 20px;
left: 50px;
overflow: hidden;
border: 1px solid red;
}
<div id="outer">
<div id="inner"> </div>
</div>
How about an svg solution?
<svg width="200" height="200" viewBox="-2 0 252 212">
<path fill="rosybrown" d="M125 0 c-81.6 60 -113.3 130 -125 200 c83.3 40 166.6 40 250 0 c-11.7 -70 -43.4 -140 -125 -200" fill="none" stroke-width="2" stroke="black" />
</svg>
Just another posibility, without using any rotation. Just clipping different circles.
.triangle {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background-color: lightblue;
overflow: hidden;
}
.triangle div {
position: absolute;
width: 100%;
height: 100%;
top: 31%;
left: 16%;
background-color: lightyellow;
border-radius: 50%;
overflow: hidden;
}
.triangle div:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
right: 30%;
background-color: red;
border-radius: 50%;
}
<div class="triangle">
<div></div>
</div>
The light colors are there just to make the construction of the triangle more visible
solution 1: Using two elements
The first example is not perfect, but does sort of answers your question:
.wrapper{
/*overflow:hidden;*/
width:0;
border-top:100px solid transparent;
border-left:100px solid red;
position:relative;
margin:50px;
transform:rotate(135deg);
}
.triangle{
width:20px;
height:100px;
background:red;
border-radius:50%;
transform:translate(-110px);
position:absolute;
top:-100px;
left:0;
}
.triangle:after{
content:"";
width:100px;
height:20px;
background:red;
border-radius:50%;
transform:translate(0px);
position:absolute;
top:90px;
left:10px;
}
.triangle:before{
content:"";
width:140px;
height:20px;
background:red;
border-radius:50%;
transform:rotate(225deg);
position:absolute;
top:40px;
left:-10px;
}
<div class="wrapper">
<div class="triangle"></div>
</div>
Please note This isn't an equilateral triangle, more of an isosceles one and could be edited into a better one no doubt!!
Solution 2: Using a single element
I was trying to create this shape using a single div element, but i was only able to generate two sides of the triangle. So, from this, I deduced that using css along requires two elements:
Two sides Of the Triangle Shown:
div {
border-left: 100px solid transparent;
border-bottom: 126px solid blue;
border-right: 100px solid transparent;
width: 0;
border-radius:50%;
position: relative;
}
div:after,
div:before {
content: "";
position: absolute;
height: 130px;
width: 20px;
border-radius: 50%;
top: -15px;
background: blue;
}
div:after {
left: -50px;
transform: rotate(40deg);
}
div:before {
left: 30px;
transform: rotate(-40deg);
}
<div></div>
I am guessing that svg may be a better option (note: I do not know svg, that seems like #chipChocolate.pys's area of expertise). So using 'just pseudo effects', I think you're looking to use two elements (but I'd like to see be proved wrong!). The 'single element' doesn't quite seem right, but may or may not be perfect for you
Pure CSS
Using different transforms.
I created three sectors using transform: rotate(30deg); and transform-origin: 0% 100%; Then I transformed their parent containers (scaleX: -1; for the left side). Done.
This can be done with just one pair of #cont and #circ elements, but I used different tags just for demonstrating better.
#cont {
height: 300px;
width: 300px;
overflow: hidden;
position:relative;
}
#circ {
height: 300px;
width: 300px;
background: black;
border-radius: 0 300px 0 0;
transform: rotate(30deg);
transform-origin: 0% 100%;
}
#cont:nth-of-type(2){
top: -300px;
transform: scaleX(-1);
}
#cont:nth-of-type(3){
top: -600px;
transform: rotate(30deg);
transform-origin: 0% 100%;
}
#cont:nth-of-type(3) > #circ {
border-radius: 0 0 300px 0;
transform-origin: 0% 0%;
}
<div id="cont">
<div id="circ">
</div>
</div>
<div id="cont">
<div id="circ">
</div>
</div>
<div id="cont">
<div id="circ">
</div>
</div>
Note: For a real website, almost always use SVG. But creating shapes with CSS is an art which mustn't be killed.
Here is my attempt at this. I think this is the best way to do it, using 1 element and :before :after.
Using the div as the base element (the bottom) we can line up the other 2 above it keeping the size and shape equal.
div {
width: 120px;
height: 60px;
background: red;
border-radius: 50%;
position: relative;
margin: 100px;
}
div:before, div:after {
content: "";
display: block;
background: red;
border-radius: 50%;
position: absolute;
width: 60px;
height: 120px;
top: -70px;
}
div:before {
transform: rotate(30deg);
left: 8px;
}
div:after {
transform: rotate(-30deg);
right: 8px;
}
<div></div>
Edit:
Another Attempt, slight tweaking from the first.
div {
width: 100px;
height: 50px;
background: red;
border-radius: 50%;
position: absolute;
top: 10px;
left: 70px;
margin: 100px;
}
div:before,
div:after {
content: "";
display: block;
background: red;
border-radius: 50%;
position: absolute;
width: 36px;
height: 106px;
top: -65px;
}
div:before {
transform: rotate(28deg);
left: 8px;
border-right: 10px solid red;
}
div:after {
transform: rotate(-28deg);
right: 8px;
border-left: 9px solid red;
}
<div></div>
I like the challenge :)
I recently have come to love the more complex border radius variations. I'm sure with some more fiddling and decent math calculations you can get rid of the rough edges where the different sides meet. No time for it now unfortunately.
.triangle {
position: absolute;
top: 100px;
left: 100px;
border-left: 25px solid transparent;
border-bottom: 40px solid blue;
border-right: 25px solid transparent;
width: 0;
border-bottom-right-radius: 80px 70px;
border-bottom-left-radius: 0 0;
transform: rotate(160deg);
}
.triangle:after {
content: '';
position: absolute;
border-left: 25px solid transparent;
border-bottom: 40px solid CornflowerBlue;
border-right: 25px solid transparent;
width: 0;
left: -54px;
top: -12px;
border-bottom-right-radius: 80px 70px;
border-bottom-left-radius: 0 0;
transform: rotate(120deg);
}
.triangle:before {
content: '';
position: absolute;
border-left: 25px solid transparent;
border-bottom: 40px solid darkblue;
border-right: 25px solid transparent;
width: 0;
top: -30px;
left: -29px;
border-bottom-right-radius: 80px 70px;
border-bottom-left-radius: 0 0;
transform: rotate(240deg);
}
<div class="triangle"></div>

How to center a CSS Hexagon

Not sure how to center this hexagon, setting margin: auto; doesn't effect the whole shape. Grateful if anyone could help, thanks in advance.
.hexagon {
position: absolute;
width: 300px;
height: 173.21px;
background-color: #fff;
}
.hexagon:before,
.hexagon:after {
content: "";
position: absolute;
margin-left: auto;
margin-right: auto;
border-left: 150px solid transparent;
border-right: 150px solid transparent;
}
.hexagon:before {
bottom: 100%;
border-bottom: 86.60px solid #fff;
position: absolute;
margin-left: auto;
margin-right: auto;
}
.hexagon:after {
position: absolute;
top: 100%;
width: 0;
border-top: 86.60px solid #fff;
}
margin:auto won't work if you have absolutely positioned divs so to center the hexagon, you have to add top:50%, left:50% and margin: -86.6px 0 0 -150px. The -86.6px is half the height of your hexagon and -150px is the half of the width. Also you have to make its parent position relative with a height of 100%.
HTML
<div class="hexagon"></div>
CSS
html,body{
background-color:#333;
height: 100%;
width: 100%;
position:relative;
}
.hexagon {
top: 50%;
left: 50%;
margin: -86.6px 0 0 -150px ;
}
Fiddle
If you just mean centering horizontally, you could do this: http://codepen.io/pageaffairs/pen/fxoHp
.hexagon {left: 0; right: 0; margin: auto;}
You can put it into another div which has margin:auto. see code here http://jsfiddle.net/oswxj9c5/
html:
<div class="parent">
<article>
<div class="hexagon">
</div>
</article>
</div>
css:
.parent {
position:relative;
background:blue;
width:900px;
height:500px;
margin:auto;
}
article {
margin:auto;
width:300px;
height:300px;
background:transparent;
}
.hexagon {
position: absolute;
width: 300px;
height: 173.21px;
background-color: red;
top:150px;
margin:auto;
}
.hexagon:before,
.hexagon:after {
content: "";
position: absolute;
margin-left: auto;
margin-right: auto;
border-left: 150px solid transparent;
border-right: 150px solid transparent;
}
.hexagon:before {
bottom: 100%;
border-bottom: 86.60px solid red;
position: absolute;
margin-left: auto;
margin-right: auto;
}
.hexagon:after {
position: absolute;
top: 100%;
width: 0;
border-top: 86.60px solid red;
}

Resources