How to achieve curved top pointer - html

Can anyone please help with this? How to achieve the attached button with CSS only(no image)?
This is my code so far:
.triangle-up {
width: 0;
height: 0;
border-left: 25px solid transparent;
border-right: 25px solid transparent;
border-bottom: 50px solid #555;
}
<div class="triangle-up"></div>

Use pseudo element where you apply a radial-gradient:
.box {
margin:60px 10px 0;
display:inline-block;
color:#fff;
text-align:center;
padding:10px 30px;
background:green;
border-radius:50px;
position:relative;
}
.box:before {
content:"";
position:absolute;
bottom:100%;
left:50%;
width:60px;
height:25px;
transform:translateX(-50%);
background:
radial-gradient(farthest-side at top left , transparent 98%,green 100%) left,
radial-gradient(farthest-side at top right, transparent 98%,green 100%) right;
background-size:50.2% 100%;
background-repeat:no-repeat;
}
body {
background:pink;
}
<div class="box">text here</div>
<div class="box">more and more text here</div>
<div class="box">2 lines <br>of text</div>
Another idea in case you want any kind of coloration:
.box {
margin:60px 10px 0;
display:inline-block;
color:#fff;
text-align:center;
padding:10px 30px;
background-image:linear-gradient(60deg,yellow,purple,green,blue);
background-size:100% calc(100% + 25px);
background-position:bottom;
border-radius:50px;
position:relative;
z-index:0;
}
.box:before {
content:"";
position:absolute;
z-index:-1;
bottom:0;
left:0;
right:0;
height:calc(100% + 25px);
background-image:inherit;
-webkit-mask:
radial-gradient(farthest-side at top left , transparent 98%,#fff 100%) left,
radial-gradient(farthest-side at top right, transparent 98%,#fff 100%) right;
mask:
radial-gradient(farthest-side at top left , transparent 98%,#fff 100%) left,
radial-gradient(farthest-side at top right, transparent 98%,#fff 100%) right;
-webkit-mask-size:30px 25px;
mask-size:30px 25px;
-webkit-mask-position:calc(50% - 15px) 0,calc(50% + 15px) 0;
mask-position:calc(50% - 15px) 0,calc(50% + 15px) 0;
-webkit-mask-repeat:no-repeat;
mask-repeat:no-repeat;
}
body {
background:pink;
}
<div class="box">text here</div>
<div class="box" style="
background-image:linear-gradient(160deg,white,red,black,orange);">more and more text here</div>
<div class="box" style="
background-image:linear-gradient(180deg,blue 20%,violet 20%,black);">2 lines <br>of text</div>

you can use the shadow on both rounded pseudos
.bubble {
position: relative;
background: #00aabb;
border-radius: 0.4em;
width: 200px;
height: 100px;
}
.bubble:after,
.bubble:before {
content: "";
position: absolute;
height: 3em;
width: 3em;
border-radius: 50%;
top: 100%;
margin: -1px;
}
:after {
left: 50%;
box-shadow: -0.8em -1.4em 0 -0.5em #00aabb
}
:before {
right: 50%;
box-shadow: 0.8em -1.4em 0 -0.5em #00aabb;
}
<div class='bubble'></div>
to understand how it works, give a background to the pseudo and another color to the shadows. You'll be able to reproduce for the sides or the top. It's a matter of the circle size and shadow's size and direction.

One option is to create a normal rectangle and then position two circles over it, such that they create a curved point.
In the demo below, this rectangle is represented by the .point div, and the circles are represented by the pseudo-elements ::before and ::after.
.caption {
position: relative;
width: 350px;
margin-top: 40px;
}
.caption>.content {
width: 100%;
height: 100%;
padding: 10px;
box-sizing: border-box;
border-radius: 30px;
background-color: green;
color: white;
text-align: center;
}
.caption>.point {
position: absolute;
left: 50%;
top: -30px;
width: 30%;
height: 30px;
transform: translateX(-50%) translateZ(1px);
overflow: hidden;
background-color: green;
}
.caption>.point::before,
.caption>.point::after {
content: '';
display: block;
width: 100%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
background-color: white;
}
.caption>.point::before {
transform: translateX(-49%) translateY(-50%);
}
.caption>.point::after {
transform: translateX(49%) translateY(-50%);
}
<div class="caption">
<div class="point"></div>
<div class="content">This is some text!</div>
</div>
Here is a more visual demonstration of what the code is actually doing. The ::before and ::after elements are represented by the red circles. I've reduced the transparency of their fill to 50% so you can see which portion of the .point div they're cutting off.
.caption {
position: relative;
width: 350px;
margin-top: 40px;
}
.caption>.content {
width: 100%;
height: 100%;
padding: 10px;
box-sizing: border-box;
border-radius: 30px;
background-color: green;
color: white;
text-align: center;
}
.caption>.point {
position: absolute;
left: 50%;
top: -30px;
width: 30%;
height: 30px;
transform: translateX(-50%) translateZ(1px);
background-color: green;
}
.caption>.point::before,
.caption>.point::after {
content: '';
display: block;
width: 100%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
background-color: rgba(255,255,255,0.5);
border: 1px solid red;
}
.caption>.point::before {
transform: translateX(-49%) translateY(-50%);
}
.caption>.point::after {
transform: translateX(49%) translateY(-50%);
}
<div class="caption">
<div class="point"></div>
<div class="content">This is some text!</div>
</div>

Related

How to add Transparent Cicle Cut Effect on Div? [duplicate]

I managed to achieve this effect: http://jsfiddle.net/6z3msdwf/1/ but I am not really happy with the markup. Also, there is an weird bug in IE 10/11 where a 1px gap is shown when you resize the window.
Is there any other way to do this? Or maybe fix this one in IE.
EDIT The circle must not use a border, it should be transparent.
body,
html {
font-size: 18px;
}
body {
background-color: #fff
}
.avatar {
width: 90px;
height: 90px;
position: absolute;
background-color: red;
top: -115px;
left: 5px;
border-radius: 80px;
}
.wrap {
display: block;
margin: 100px auto 0 auto;
width: 90%;
position: relative;
}
.rect-left,
.rect-right {
position: relative;
width: 50%;
height: 150px;
float: left;
}
.rect-left {
margin-left: -50px;
}
.rect-right {
margin-right: -50px;
}
.inner {
position: absolute;
top: 0;
left: 50px;
right: 0;
bottom: 0;
height: 100%;
background: rgba(0, 0, 0, 0.8);
}
.rect-left .inner {
left: 50px;
right: 0;
-webkit-border-top-left-radius: 6px;
-webkit-border-bottom-left-radius: 6px;
-moz-border-radius-topleft: 6px;
-moz-border-radius-bottomleft: 6px;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
.rect-right .inner {
left: 0;
right: 50px;
-webkit-border-top-right-radius: 6px;
-webkit-border-bottom-right-radius: 6px;
-moz-border-radius-topright: 6px;
-moz-border-radius-bottomright: 6px;
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
.rect {
float: left;
height: 100px;
width: 100px;
background: rgba(0, 0, 0, 0.8);
position: relative;
top: 50px;
}
.circle {
display: block;
width: 100px;
height: 50px;
top: -50px;
left: 0;
overflow: hidden;
position: absolute;
}
.circle:after {
content: '';
width: 100px;
height: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
border-radius: 100px;
background: rgba(0, 0, 0, 0);
position: absolute;
top: -110px;
left: -40px;
border: 40px solid rgba(0, 0, 0, 0.8);
}
<div class="wrap">
<div class="rect-left">
<div class="inner"></div>
</div>
<div class="rect"> <span class="circle"></span>
<div class="avatar"></div>
</div>
<div class="rect-right">
<div class="inner"></div>
</div>
</div>
You can do this using a single element (plus a pseudo element) using radial-gradient background for the parent element while the pseudo-element creates the circle.
div:before { /* creates the red circle */
position: absolute;
content: '';
width: 90px;
height: 90px;
top: -75px; /* top = -75px, radius = 45px, so circle's center point is at -30px */
left: calc(50% - 45px);
background-color: red;
border-radius: 50%;
}
div {
position: relative;
margin: 100px auto 0 auto;
width: 90%;
height: 150px;
border-radius: 6px;
/* only the below creates the transparent gap and the fill */
background: radial-gradient(50px 50px at 50% -30px, rgba(0, 0, 0, 0) 49.5px, rgba(0, 0, 0, .8) 50.5px); /* use same center point as with concentric circles but larger radius */
}
/* just for demo */
body,
html {
font-size: 18px;
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div></div>
You could use a circular gradient
div {
height: 150px;
margin: 5em 2em;
background: radial-gradient(circle at top center, transparent, transparent 70px, black 70px, black);
border-radius: 8px;
position: relative;
}
.circle {
width: 120px;
height: 120px;
background: red;
border-radius: 50%;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
}
body {
background-image: url(http://www.fillmurray.com/1000/1000);
background-size: cover;
}
<div>
<span class="circle"></span>
</div>
With an inline svg it is very simple :
a circle element
a path element with an arc comand for the indented circle
body{background:url('http://i.imgur.com/5NK0H1e.jpg');background-size:cover;
svg{display:block;}
<svg viewbox="0 0 10 3.5">
<path d="M4.2 1 A0.85 0.85 0 0 0 5.8 1 H10 V3.5 H0 V1z" fill="#333" />
<circle cx="5" cy="0.7" r="0.7" fill="red" />
</svg>
Or if you really want to use CSS, you can achieve the shape with the approach described in: Transparent half circle cut out of a div.
Note that the code is much longer than the svg approach:
.container{
position:relative;
height:250px;
text-align:center;
}
.circle{
position:relative;
display:inline-block;
width:100px; height:100px;
background:red;
border-radius:50%;
z-index:2;
}
.rect{
position:absolute;
top:50px; left:0;
width:100%; height:200px;
border-radius:10px;
overflow:hidden;
z-index:1;
}
.rect:before{
content:'';
position:absolute;
top:-60px; left:50%;
margin-left:-60px;
width:120px; height:120px;
border-radius:50%;
box-shadow:0 0 0 99999px #333;
}
body{background:url('http://i.imgur.com/5NK0H1e.jpg');background-size:cover;
<div class="container">
<div class="circle"></div>
<div class="rect"></div>
</div>

Embed and position two rotated div in the corner of a rectangle properly?

I am trying to create a header with a corner of it showing two icons in a custom way.
Issues:
Modifying the icons' size is impossible without destroying everything (emoji in this example).
The code seems way more complicated than what I think is achievable.
Hard to properly position the icons.
I created a CodePen, which can be found here.
Current result:
HTML/CSS:
.mainContent {
margin-left: 150px;
}
.title {
margin: 18px 0 10px;
}
.header {
position: relative;
z-index: -2;
height: 150px;
background-image: linear-gradient(#ff9d2f, #ff6126);
border-bottom-left-radius: 60% 15%;
border-bottom-right-radius: 60% 15%;
padding-top: 10px;
overflow: hidden;
}
.iconHolder i {
color: white;
z-index: 2;
position: relative;
left: 60px;
}
.iconHolderSecondary i {
color: black;
z-index: 2;
position: relative;
left: 15px;
top: 50px;
}
.typeHolders {
position: relative;
width: auto;
}
.iconHolder::before {
content: "";
display: block;
position: absolute;
left: 0;
bottom: 0;
width: 250px;
height: 200px;
z-index: -1;
transform: skewY(-40deg);
background: linear-gradient(#4e4376, #2b5876);
background-size: cover;
border-bottom: 0.2em solid #fff;
}
.iconHolderSecondary::before {
content: "";
display: block;
position: absolute;
left: -130px;
bottom: -118px;
float: left;
width: 150px;
height: 200px;
z-index: 0;
transform: rotate(-40deg);
background: lightblue;
background-size: cover;
}
<div class="header">
<div class="typeHolders">
<div class="iconHolder">
<i>😇</i>
</div>
<div class="iconHolderSecondary">
<i>🤮</i>
</div>
</div>
<div class="mainContent">
<h2 class="title">A title</h2>
<p class="subtitle">Some subtitle</p>
</div>
</div>
You can simplify your code like below by moving all the elements that create the background to main container and remove a lot of divs. Then you can easily adjust the position of the icons:
.header {
position: relative;
z-index: 0;
height: 150px;
background-image: linear-gradient(#ff9d2f, #ff6126);
border-bottom-left-radius: 60% 15%;
border-bottom-right-radius: 60% 15%;
padding-top: 10px;
overflow: hidden;
}
.header:before {
content: "";
position: absolute;
z-index:-1;
top: 0;
left: 0;
bottom: 0;
width: 150px; /*same value*/
background:
linear-gradient(205deg, transparent 32.5%, lightblue 33%),
/*adjust the degree to get the need direction*/
linear-gradient(120deg,#4e4376, #2b5876);
border-right: 3px solid #fff;
transform-origin: top;
transform: skewX(-45deg);
}
.iconHolder {
width:150px; /*same value*/
float:left;
height:100%;
text-align:center; /*make the first one in the middle horizontally*/
}
/*make the second one in the middle vertically*/
.iconHolder span:last-child {
position:absolute; /*it will be relative to the main container*/
top:50%;
transform:translateY(-50%);
left:10px;
}
.title {
padding-top:20px;
}
<div class="header">
<div class="iconHolder">
<span>😇</span>
<span>😇</span>
</div>
<h2 class="title">A title</h2>
<p class="subtitle">Some subtitle</p>
</div>
In case the second gradient is not needed you can still simplify more by using multiple background:
.header {
position: relative;
height: 150px;
background:
linear-gradient(to bottom left, #2b5876 49.8%,transparent 50%) -10px 0/ calc(75px + 10px) 50%,
linear-gradient(to bottom right, #2b5876 49.8%,transparent 50%) 75px 0/ 75px 50%,
linear-gradient(to bottom right, lightblue 49.8%,transparent 50%) left top/150px 100%,
/*we add more pixel to the size for the border effect*/
linear-gradient(to bottom right, #fff 49.8%,transparent 50%) left/156px calc(100% + 6px),
linear-gradient(#ff9d2f, #ff6126);
background-repeat:no-repeat;
border-bottom-left-radius: 60% 15%;
border-bottom-right-radius: 60% 15%;
padding-top: 10px;
overflow: hidden;
}
.iconHolder {
width:150px; /*same value*/
float:left;
height:100%;
text-align:center; /*make the first one in the middle horizontally*/
}
/*make the second one in the middle vertically*/
.iconHolder span:last-child {
position:absolute; /*it will be relative to the main container*/
top:50%;
transform:translateY(-50%);
left:10px;
}
.title {
padding-top:20px;
}
<div class="header">
<div class="iconHolder">
<span>😇</span>
<span>😇</span>
</div>
<h2 class="title">A title</h2>
<p class="subtitle">Some subtitle</p>
</div>

Re-sizing a cube

I have a set of codes from the cube created using CSS.
However, how do I resize this into a bigger cube (for example, 200px)? I have tried but everytime I try doing it, it goes out of position..
.mainDiv {
position: relative;
width: 206px;
height: 190px;
margin: 0px auto;
margin-top: 100px;
}
.square {
width: 100px;
height: 100px;
background: #c52329;
border: solid 2px #FFF;
transform: skew(180deg, 210deg);
position: absolute;
top: 43px;
}
.square2 {
width: 100px;
height: 100px;
background: #c52329;
border: solid 2px #FFF;
transform: skew(180deg, 150deg);
position: absolute;
left: 102px;
top: 43px;
}
.square3 {
width: 114px;
height: 100px;
background: #c52329;
border: solid 2px #FFF;
transform: rotate(150deg) translate(-40px, -16px) skew(30deg, 0deg);
position: absolute;
left: 0px;
top: -32px;
}
<div class="mainDiv">
<div class="square"></div>
<div class="square2"></div>
<div class="square3"></div>
</div>
You may first adjust your code to make the shape easier by reducing the code and removing some fixed values then you only need to change the size of the main element to make the cube bigger or smaller:
* {
box-sizing:border-box;
}
.mainDiv {
position: relative;
width: 200px;
height: 100px;
margin: 120px auto 0;
font-size:0;
}
.mainDiv > * {
background: #c52329;
border: solid 2px #FFF;
}
.square,
.square2{
width: 50%;
height: 100%;
display:inline-block;
}
.square {
transform-origin:top left;
transform:skewY(30deg);
}
.square2 {
transform-origin:top right;
transform:skewY(-30deg);
}
.square3 {
width: calc(50% * 1.14);
height: 100%;
transform: rotate(-30deg) skewX(30deg);
position: absolute;
transform-origin:top left;
top:0;
}
<div class="mainDiv">
<div class="square"></div>
<div class="square2"></div>
<div class="square3"></div>
</div>
<div class="mainDiv" style="width:100px;height:50px;">
<div class="square"></div>
<div class="square2"></div>
<div class="square3"></div>
</div>
<div class="mainDiv" style="width:400px;height:200px;">
<div class="square"></div>
<div class="square2"></div>
<div class="square3"></div>
</div>
You can also reduce the code using pseudo-element and introduce CSS variable to control the size:
.mainDiv {
position: relative;
--d:50px;
width: calc(var(--d) * 1.73 * var(--s, 1)); /* x sqrt(3) */
height: calc(var(--d) * var(--s, 1));
margin: calc(var(--d) * var(--s, 1)) auto;
}
.mainDiv:before,
.mainDiv:after {
content: "";
width: 50%;
height: 100%;
background:
linear-gradient(#c52329,#c52329) center/calc(100% - 4px) calc(100% - 4px) no-repeat,
#fff;
display: inline-block;
}
.mainDiv:before {
transform-origin: top left;
transform: skewY(30deg);
}
.mainDiv:after {
transform-origin: top right;
transform: skewY(-30deg);
}
.mainDiv>div {
position: absolute;
width: calc(50% * 1.154); /* x (1/cos(30)) */
padding-top:50%;
transform: rotate(-30deg) skewX(30deg);
background:
linear-gradient(#c52329,#c52329) center/calc(100% - 4px) calc(100% - 4px) no-repeat,
#fff;
top: 0;
transform-origin: top left;
}
<div class="mainDiv" style="--s:0.5"><div></div></div>
<div class="mainDiv"><div></div></div>
<div class="mainDiv" style="--s:1.5"><div></div></div>
<div class="mainDiv" style="--s:2"><div></div></div>
<div class="mainDiv" style="--s:3"><div></div></div>
You can even reduce more the code by relying on some gradient as background to create one part of the shape and remove the inner div and you will only have one element at the end:
.mainDiv {
position: relative;
--d:50px;
width: calc(var(--d) * 1.73 * var(--s,1));
height: calc(var(--d) * var(--s,1));
margin: 0 auto calc(var(--d) * var(--s,1));
background:
linear-gradient(to bottom left,#c52329 47%,transparent 48.5%) bottom left,
linear-gradient(to bottom right,#c52329 47%,transparent 48.5%) bottom right,
linear-gradient(to top left,#c52329 47%,transparent 48.5%) top left,
linear-gradient(to top right,#c52329 47%,transparent 48.5%) top right;
background-size:50.5% 50.5%;
background-repeat:no-repeat;
}
.mainDiv:before,
.mainDiv:after{
content:"";
width:50%;
height: 100%;
background:
linear-gradient(#c52329,#c52329) center/calc(100% - 4px) calc(100% - 4px) no-repeat,
#fff;
display:inline-block;;
}
.mainDiv:before {
transform-origin:top left;
transform:skewY(30deg) translateY(50%);
}
.mainDiv:after {
transform-origin:top right;
transform:skewY(-30deg) translateY(50%);
}
<div class="mainDiv"></div>
<div class="mainDiv" style="--s:1.5"></div>
<div class="mainDiv" style="--s:2"></div>
<div class="mainDiv" style="--s:3"></div>
The easier solution is to scale main container up. You can try to play with values to achieve desired size and position.
.mainDiv {
position: relative;
width: 206px;
height: 190px;
margin: 0px auto;
margin-top: 100px;
transform: scale(2) translate(5px, 70px);
}
.square {
width: 100px;
height: 100px;
background: #c52329;
border: solid 2px #FFF;
transform: skew(180deg, 210deg);
position: absolute;
top: 43px;
}
.square2 {
width: 100px;
height: 100px;
background: #c52329;
border: solid 2px #FFF;
transform: skew(180deg, 150deg);
position: absolute;
left: 102px;
top: 43px;
}
.square3 {
width: 114px;
height: 100px;
background: #c52329;
border: solid 2px #FFF;
transform: rotate(150deg) translate(-40px, -16px) skew(30deg, 0deg);
position: absolute;
left: 0px;
top: -32px;
}
<div class="mainDiv">
<div class="square"></div>
<div class="square2"></div>
<div class="square3"></div>
</div>

Create footer with two different colors

I am trying to create a footer according to a design I received ...
The background color on the left is different from the right one:
I have the following markup:
<div class"wrapper">
<div class="content">
The Text here should no go over the logo
</div>
</div>
My idea is Content DIV to have the logo as background image aligned left and no repeat.
But then I don't know how to create the different color on left and right ...
And I am not sure if I can control the height so that everything aligns.
The content div is centered and has the orange border on the image ...
Thank You,
Miguel
Try this http://codepen.io/nicknameless/pen/cblzB/
I've used CSS3 and no additional markup. This should work for you. It could be cleaned up I think, this is just a quick overview to get you started.
The HTML you provided
<div class="wrapper">
<div class="content">
The Text here should no go over the logo
</div>
</div>
The CSS
html, body {
padding: 0;
margin: 0;
}
div.wrapper {
height: 40px;
background: #850000;
width: 100%;
display: block;
position: relative;
overflow: visible;
top: calc( 100px - 40px );
}
div.wrapper:before {
background: transparent url('http://placehold.it/100x100') no-repeat 0 0;
content: " ";
width: 100px;
height: 100px;
position: absolute;
bottom: 0;
left: 10%;
}
div.content {
left: calc( 10% + 100px );
padding-left: 10px;
bottom: 0;
background-color: #C70000;
display: block;
height: 40px;
position: absolute;
width: calc( 100% - ( 10% + 100px ) );
}
It's was really a pain in the ass, I recommend to take the inner rectangle as a picture, but if you really want it in CSS, here it's: http://jsfiddle.net/B97ym/
HTML:
<div class='wrapper'>
<div class="content">The Text</div>
<div class='border'>
<div class='border2'></div>
<div class='border3'></div>
<div class='logodiv'>
<div class='rectangle'></div>
</div>
</div>
CSS:
.wrapper {
width: 500px;
height: 50px;
margin: 100px auto;
position: relative;
background: linear-gradient(to right, #9c9e9f 40%, #000000 40%);
}
.content{
margin: 0 0 0 50%;
color: #ffffff;
}
.border{
width: 4em;
height: 4em;
background: #FF0000;
position: absolute;
left: 33.7%;
top: -55%;
-ms-transform: rotate(45deg); /* IE 9 */
-webkit-transform: rotate(45deg); /* Chrome, Safari, Opera */
transform: rotate(45deg);
background: linear-gradient(to top, #000000 62%, #9c9e9f 62%);
}
.border2{
width: 0.8em;
height: 4em;
background: #9c9e9f;
position: absolute;
left: 80%;
}
.border3{
width: 0.8em;
height: 0.85em;
background: #000000;
position: absolute;
left: 80%;
top: 80%;
}
.logodiv {
width: 2.5em;
height: 2.5em;
background: #ffffff;
position: absolute;
top: 18%;
left: 18%;
}
.rectangle{
width: 2.1em;
height: 2.1em;
position: relative;
background: #ffffff;
top: -42%;
left: -42%;
-ms-transform: rotate(45deg); /* IE 9 */
-webkit-transform: rotate(45deg); /* Chrome, Safari, Opera */
transform: rotate(45deg);
}
Hope it's will be helpful to someone (:
Use a CSS background-image on the wrapper layer that contains the entire logo, bars an all. Add enough margin-left on the inner layer to shove the text beyond the logo.
Create a div with two div's inside with 50% width for left and right and fixed height. Make sure you overflow the logo.
I wonder if this FIDDLE will give you a place to start.
CSS
.holder {
width: 500px;
margin: 100px auto;
position: relative;
}
.leftdiv {
width: 40%;
height: 60px;
float: left;
background-color: red;
}
.rightdiv {
width: 60%;
height: 60px;
float: left;
background-color: blue;
}
.logodiv {
width: 44px;
height: 44px;
position: absolute;
left: 157px;
top: -42px;
background-color: white;
transform: rotate(45deg);
border-left: 20px solid blue;
border-right: 20px solid red;
border-top: 20px solid red;
border-bottom: 20px solid blue;
}
.whiteout {
background-color: white;
width: 30px;
height: 60px;
border: 0px solid black;
position: absolute;
top: -60px;
left: 183px;
}

Are diagonal border lines possible in HTML / CSS?

Just realized I have yet to see this.
But can not believe it isn't possible.
I'm looking to draw a triangle in pure CSS/HTML. An equilateral if possible.
Clarification:
I don't wish to use an image to achieve this.
You would need to be able to put content inside the div.
One Solution
Diagonals are not easy. One solution is to overlay pseudo-elements to create the border, assuming you are dealing with solid background colors. Then you have to position the content to make it look nice. You could even do some text wrapping.
Here is a basic example using this code:
CSS & HTML Respectively
.triangleBorder {
position: relative;
width: 200px;
height: 173.2px; /* for equalateral = Width * (sq.root 3) / 2 */
}
.triangleBorder:before {
content: '';
width: 0;
height: 0;
position: absolute;
z-index: -2;
border: 100px solid transparent;
border-top-width: 0;
border-bottom: 173.2px solid black;
}
.triangleBorder:after {
content: '';
width: 0;
height: 0;
position: absolute;
left: 1px;
top: 1px;
z-index: -1;
border: 99px solid transparent;
border-top-width: 0;
border-bottom: 171.5px solid white;
}
.triangleBorder span {
position: absolute;
width: 100%;
text-align: center;
top: 50%;
}
<div class="triangleBorder">
<span>Content<span>
</div>
Here are a few different approaches for creating the equilateral triangle shape using CSS. Creation of diagonals is still not any easier but now the shape can at-least have a transparent background even when the body has a gradient (or) an image as its background.
Option 1: Using Pseudo-elements and Skew Transforms
In this method we use a couple of pseudo-elements and skew them in opposite directions (inward) to create the diagonal lines whereas the line at the bottom is produced using a border-bottom on the parent. We can also produce trapezoids using this approach.
Cons: This approach would not work if the body background and shape background are different and the body background is not a solid color.
.triangle {
position: relative;
width: 200px;
border-bottom: 2px solid white;
color: white;
margin: 20px auto;
overflow: hidden;
}
.shape1 {
height: 174px;
}
.shape2 {
height: 101px;
}
.triangle:before,
.triangle:after {
position: absolute;
content: '';
height: 100%;
width: 0%;
bottom: 0px;
transform-origin: left bottom;
}
.triangle:before {
left: 0px;
border-right: 2px solid white;
}
.triangle.shape1:before {
transform: skew(-30deg);
}
.triangle.shape2:before {
transform: skew(-45deg);
}
.triangle:after {
right: 0px;
border-left: 2px solid white;
}
.triangle.shape1:after {
transform: skew(30deg);
}
.triangle.shape2:after {
transform: skew(45deg);
}
.triangle span {
position: absolute;
width: 100%;
text-align: center;
top: 50%;
}
/* Just for demo */
*{
box-sizing: border-box;
}
body {
background: radial-gradient(ellipse at center, #400, #100);
}
.trapezoid {
position: relative;
border-bottom: 2px solid white;
color: white;
margin: 20px auto;
width: 200px;
height: 50px;
}
.trapezoid:before,
.trapezoid:after {
position: absolute;
content: '';
height: 100%;
width: 40%;
bottom: -1px;
border-top: 2px solid white;
transform-origin: left bottom;
}
.trapezoid:before {
left: 0px;
border-left: 2px solid white;
transform: skew(-45deg);
}
.trapezoid:after {
right: 0px;
border-right: 2px solid white;
transform: skew(45deg);
}
.trapezoid span {
position: absolute;
width: 100%;
text-align: center;
top: 30%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle shape1'>
<span>content</span>
</div>
<div class='triangle shape2'>
<span>content</span>
</div>
<br/>
<!-- Just something extra to illustrate -->
<div class='trapezoid'>
<span>content</span>
</div>
<br/>
Here is a variation of Option 1 which would work when the background of the body and that of the shape are different and the body background is a solid color.
.triangle{
position: relative;
width: 200px;
border-bottom: 2px solid black;
color: red;
background: beige;
margin: 20px auto;
overflow: hidden;
}
.shape1{
height: 174px;
}
.shape2{
height: 101px;
}
.triangle:before, .triangle:after{
position: absolute;
content: '';
height: 101%;
width: 100%;
bottom: 0px;
background: red;
transform-origin: left bottom;
}
.triangle:before{
left: -200px;
border-right: 2px solid black;
}
.triangle.shape1:before{
transform: skew(-30deg);
}
.triangle.shape2:before{
transform: skew(-45deg);
}
.triangle:after{
right: -200px;
border-left: 2px solid black;
}
.triangle.shape1:after{
transform: skew(30deg);
}
.triangle.shape2:after{
transform: skew(45deg);
}
.triangle span{
position: absolute;
width: 100%;
text-align: center;
top: 50%;
}
/* Just for demo */
*{
box-sizing: border-box;
}
body{
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle shape1'>
<span>content</span>
</div>
<div class='triangle shape2'>
<span>content</span>
</div>
Here is another variation of Option 1 which supports gradient background for both inside and outside the triangle shape.
.triangle {
position: relative;
width: 200px;
border-bottom: 2px solid white;
color: white;
margin: 20px auto;
overflow: hidden;
}
.shape1 {
height: 174px;
}
.shape2 {
height: 101px;
}
.triangle:before,
.triangle:after {
position: absolute;
content: '';
height: 99%;
width: 50%;
z-index: -1;
transform-origin: left bottom;
}
.triangle:before {
left: 0px;
top: 100%;
border-top: 3px solid white;
background: linear-gradient(90deg, #003333, #773333);
}
.triangle.shape1:before {
border-top: 4px solid white;
transform: skewY(-60deg);
}
.triangle.shape2:before {
transform: skewY(-45deg);
}
.triangle:after {
right: 0px;
top: 0%;
border-top: 3px solid white;
background: linear-gradient(90deg, #773333, #FF3333);
}
.triangle.shape1:after {
border-top: 4px solid white;
transform: skewY(60deg);
}
.triangle.shape2:after {
transform: skewY(45deg);
}
.triangle span {
position: absolute;
width: 100%;
text-align: center;
top: 50%;
}
/* Just for demo */
*{
box-sizing: border-box;
}
body {
background: radial-gradient(ellipse at center, #400, #100);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle shape1'>
<span>content</span>
</div>
<div class='triangle shape2'>
<span>content</span>
</div>
Screenshot:
Triangles with different angles can be easily created by modifying the skew angle and the height of the parent div. But, as we are using skew the borders tend to become thinner as the skew angle approaches 90deg (or -90deg) but that shouldn't be too big a problem because with such high angles you can barely have fit any text inside.
Option 2: Using Linear Gradients
In this method, we use a couple of angled linear-gradient backgrounds (each of which are 50% width of the container) and slant them in opposite directions to produce the diagonal lines.
.triangle {
position: relative;
border-bottom: 2px solid white;
color: white;
margin: 20px auto;
height: 174px;
width: 200px;
background: linear-gradient(to top left, transparent 49.5%, white 49.5%, white 50.5%, transparent 50.5%), linear-gradient(to top right, transparent 49.5%, white 49.5%, white 50.5%, transparent 50.5%);
background-size: 50% 100%;
background-position: 1px 0px, 99px 0px;
background-repeat: no-repeat;
}
.triangle span {
position: absolute;
width: 100%;
text-align: center;
top: 50%;
}
/* Just for demo*/
body {
background: radial-gradient(ellipse at center, #400, #100);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='triangle'>
<span>content</span>
</div>
Cons: Angled gradients are known for producing jagged lines.
Note: Irrespective of which approach is chosen, you would still have to do text wrapping to make the text stay inside the shape.