I am trying to create a speech bubble using two divs, one is a triangle and the other is a rectangle.
This is the code:
#box {
width: 200px;
height: 80px;
background-color: #ccc;
position: relative;
left: 300px;
top: 180px;
padding: 5px;
border-radius: 10px;
-moz-box-shadow: 0 0 5px #333;
-webkit-box-shadow: 0 0 5px #333;
box-shadow: 0 0 5px #333;
}
#tri {
position: absolute;
top: -15px;
left: 40px;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 15px solid #ccc;
float: left;
margin: 2px 5px 0px 0px;
-moz-box-shadow: 0 0 5px #333;
-webkit-box-shadow: 0 0 5px #333;
box-shadow: 0 0 5px #333;
}
<div id="box">
<div id="tri"></div>
Some text
</div>
This problem is that something happens at the point where the triangle connects to the box. The shadow doesn't go around the triangle. Is it possible to fix this so that the shadow goes around the box and continues around the triangle?
Using that technique, you wont be able to place a shadow on the triangle shape.
We can create the triangle with an :after pseudo-element and create the boxes main shadow with a :before pseudo-element.
The Triangle
The triangle looks like a diamond and the background of the box overlaps the diamond to make it look like a triangle:
This: becomes this:
The z-index: -1 places both pseudo-elements underneath their parents background.
The main shadow
The main shadow needs to be placed on a pseudo-element so that it can be overlapped by the triangle background, whilst at the same time, the triangles bottom half is overlapped by the elements background. This image shows the layers:
Full Example
#box {
width: 200px;
height: 80px;
background: #CCC;
position: relative;
left: 300px;
top: 180px;
padding: 5px;
border-radius: 10px;
}
#box:before,
#box:after {
content: '';
position: absolute;
box-shadow: 0 0 5px #333;
z-index: -1;
}
#box:before {
height: 100%;
width: 100%;
left: 0;
top: 0;
border-radius: 10px;
}
#box:after {
background: #CCC;
height: 20px;
width: 20px;
top: -10px;
left: 50%;
margin-left: -5px;
transform: rotate(45deg);
z-index: -1;
}
<div id="box">
Some text
</div>
Use this
DEMO
.arrow_box {
position: relative;
top:150px;
background: #88b7d5;
border: 4px solid #c2e1f5;
width:200px;
height:80px;
}
.arrow_box:after, .arrow_box:before {
bottom: 100%;
left: 20%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.arrow_box:after {
border-color: rgba(136, 183, 213, 0);
border-bottom-color: #88b7d5;
border-width: 30px;
margin-left: -30px;
}
.arrow_box:before {
border-color: rgba(194, 225, 245, 0);
border-bottom-color: #c2e1f5;
border-width: 36px;
margin-left: -36px;
}
No, there's no way to apply a shadow to that triangle. The shadow applies to a div, and divs are square. You could use an image or svg instead.
Or you could try this. Remove the shadow from the triangle and add this code.
#tri:after {
content:'';
position:absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 15px solid rgba(0,0,0,.25);
width: 0;
height: 0;
top: -2px;
right: -10px;
z-index: -1;
}
I know it is not the same but, it's something.
try this
<div id="box">
<div class="mask"></div>
<div id="tri"></div>
.mask{
background-color:#ccc;
width:100%;
height:100%;
position:absolute;
top:0;
left:0;
}
Related
I need to create a box with an arrow at the left bottom corner. My problem is to get the asymmetric triangle.
Here an example for the bottom border of the box with an triangle at the left bottom corner:
This is my attempt so far:
.box {
width: 150px;
height: 75px;
background-color: black;
color: #fff;
padding: 20px;
position: relative;
margin: 40px;
float: left;
}
.box.arrow-bottom:after {
content: " ";
position: absolute;
left: 0px;
bottom: -15px;
border-top: 15px solid black;
border-right: 15px solid transparent;
border-left: 15px solid transparent;
border-bottom: none;
}
<div class="box arrow-bottom">
This is a box with some content and an arrow at the bottom.
</div>
I edited the border width a bit, and added transform: skewX(). You may play with the right amount for the skew.
In addition the :after changed to :before and I played with left property and removed the right.
hope it helps:
.box {
width: 150px;
height: 75px;
background-color: black;
color: #fff;
padding: 20px;
position: relative;
margin: 40px;
float: left;
}
.box.arrow-bottom:before {
content: " ";
position: absolute;
left: 8px;
bottom: -15px;
border-top: 15px solid black;
border-right: 0px solid transparent;
border-left: 15px solid transparent;
border-bottom: none;
transform: skewX(20deg);
}
<div class="box arrow-bottom">
This is a box with some content and an arrow at the bottom.
</div>
Write below code to generate arrow
.box {
position: relative;
background: #00aabb;
border-radius: .4em;
}
.box:after {
content: '';
position: absolute;
bottom: 0;
left: 0%;
width: 0;
height: 0;
border: 20px solid transparent;
border-top-color: #00aabb;
border-bottom: 0;
border-right: 0;
margin-left: -10px;
margin-bottom: -20px;
}
Here is an idea using multiple background and relying on conic-gradient() 1
.box {
width: 150px;
height: 75px;
background:
conic-gradient(transparent 314deg, black 315deg,black 340deg,transparent 342deg)
bottom -30px left 0/60px 60px border-box,
black padding-box;
background-repeat:no-repeat;
color: #fff;
padding: 20px;
border-bottom:30px solid transparent; /*the space for the gradient*/
margin: 40px;
}
<div class="box arrow-bottom">
This is a box with some content and an arrow at the bottom.
</div>
Here is the gradient alone to better see how it's working:
.box {
width: 60px;
height: 60px;
background:
conic-gradient(red 314deg, black 315deg,black 340deg,red 342deg)
}
<div class="box">
</div>
1:Supported only on chrome actually
Another idea with linear-gradient but without transparency:
.box {
width: 150px;
height: 75px;
background:
linear-gradient(to bottom left,transparent 49%,#fff 50%) bottom 0 left 0/30px 30px border-box,
linear-gradient(250deg, transparent 10px,#000 11px) bottom 0 left 0/30px 30px border-box,
black padding-box;
background-repeat:no-repeat;
color: #fff;
padding: 20px;
border-bottom:30px solid transparent; /*the space for the gradient*/
margin: 40px;
}
<div class="box arrow-bottom">
This is a box with some content and an arrow at the bottom.
</div>
You could use an SVG as the background of the pseudoelement, e.g.
.box.arrow-bottom:after {
content: " ";
position: absolute;
right: 30px;
bottom: -30px;
width: 22px;
height: 30px;
color: #000;
background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 22 30"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<path d="M0 0 L22 30 L15 0 z" fill="%23000" /></svg>');
}
Example Codepen
I have updated css with transform:rotate and border, check it
.box {
width: 150px;
height: 75px;
background-color: black;
color: #fff;
padding: 20px;
position: relative;
margin: 40px;
float: left;
}
.box.arrow-bottom:after {
content: " ";
position: absolute;
right: 7px;
bottom: -41px;
border-top: 45px solid black;
border-right: 15px solid transparent;
border-left: 0px solid black;
border-bottom: none;
transform: rotate(20deg);
}
.box.arrow-bottom:before {
content: " ";
position: absolute;
left: 7px;
bottom: -41px;
border-top: 45px solid black;
border-right: 0px solid transparent;
border-left: 15px solid transparent;
border-bottom: none;
transform: rotate(-20deg);
}
<div class="box arrow-bottom">
This is a box with some content and an arrow at the bottom.
</div>
How to create border triangle?
The only thing I can think of to make this is to make a triangle
.triangle {
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 20px solid #8e8e8e;
}
But this is a solid triangle, is there a way to make it look like the triangle extends the border
Create an :after or :before element that absolutely positions at the bottom of your div.
.box {
position: relative;
background-color: #F00;
border: 1px solid #000;
width: 50px;
height: 50px;
}
.box:after {
content: "";
width: 16px;
height: 16px;
position: absolute;
background-color: #FFF;
bottom: -8px; /* half of the elements width/height */
left: 50%;
transform: translateX(-50%) rotate(45deg);
border-bottom: 1px solid #000;
border-right: 1px solid #000;
}
<div class="box">
I've made the :after element white so you can see what's happening inside of it.
You need to move triangle element to under sub layout.
I added more triangle for the border design.
.balon {
width: 350px;
height: 120px;
border: 5px solid #2C6DBF;
margin: 50px auto;
position: relative;
border-radius: 8px;
}
.balon::after, .balon::before {
width: 0;
height: 0;
content: '';
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-top: 21px solid #fff;
position: absolute;
bottom: -19px;
right: 0;
left: 0;
margin: auto;
}
.balon::before {
border-left-width: 20px;
border-right-width: 20px;
border-top-width: 25px;
border-top-color: #2C6DBF;
bottom: -25px;
}
<div class="balon">
</div>
I have tried to tweak the CSS from
http://jsfiddle.net/wn7JN/ to place an arrow in a <div> in the top left corner (see image below), but I can't seem to figure out how :before and :after in CSS work. Every time I update the bottom and left parameters I am left with a black arrow in the top left corner - I think the proper rotation is transform: rotate(220deg) but that is really a guess.
Edit: Is it possible to do this same CSS trick with an rgba color such as rgba(255, 123, 172, 0.25)? When I test it out the transparency becomes an issue with the border overlap.
Any help would be greatly appreciated.
.bubble {
position: relative;
width: 400px;
height: 250px;
padding: 0px;
background: #FFFFFF;
border: #000 solid 1px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.bubble:after {
content: "";
position: absolute;
bottom: -25px;
left: 175px;
border-style: solid;
border-width: 25px 25px 0;
border-color: #FFFFFF transparent;
display: block;
width: 0;
z-index: 1;
}
.bubble:before {
content: "";
position: absolute;
top: 250px;
left: 174px;
border-style: solid;
border-width: 26px 26px 0;
border-color: #000 transparent;
display: block;
width: 0;
z-index: 0;
}
<div class="bubble"> </div>
Try like this. Added a working copy.
.bubble {
position: relative;
background:#cbe8f0;
height: 100px;
width:170px;
margin-left:30px;
border-radius:2px;
}
.bubble:after{
content:'';
position:absolute;
border:10px solid transparent;
border-top:10px solid #cbe8f0;
top:0px;
left:-10px;
}
<div class="bubble"> </div>
You can ty this solution too based on the jsfiddle.
.bubble:after
{
content: "";
position: absolute;
top:0px;
left: -21px;
border-style: solid;
border-width: 24px 0px 0px 28px;
border-color: #FFFFFF transparent;
display: block;
width: 0;
z-index: 1;
}
.bubble:before
{
content: "";
position: absolute;
top:-1px;
left:-23px;
border-style: solid;
border-width:20px 0px 0px 23px;
border-color: #000 transparent;
display: block;
width: 0;
z-index: 0;
}
http://jsfiddle.net/wn7JN/1295/
So, here's your bubble code:
.bubble {
position: relative;
width: 400px;
height: 250px;
padding: 0px;
background: #FFFFFF;
border: #000 solid 1px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
Add this line to the bottom of that: margin-left:25px; This allows there to be room to the side of your bubble for the arrow to even show up. Otherwise, it's there, but you can't see it.
for your bubble:after, change the bottom: -25px to top: 21px and change left: 175px to left: -37px, and add transform: rotate(90deg); to the bottom.
for your bubble:before, change the top: 250px to top: 20px and change left: 174px to left: -39px, and add transform: rotate(90deg); to the bottom.
You will wind up with something like this:
1
Final fiddle: http://jsfiddle.net/eq6mhbwy/
I want to add a label on some of my elements on a website and design for a label that is a flag with an inverted V-shaped cut at the bottom.
So far I have this:
HTML
<div class="css-shapes"></div>
CSS
.css-shapes{
border-left: 99px solid #f00fff;
border-right: 99px solid #f00fff;
border-bottom: 39px solid transparent;
}
http://jsfiddle.net/yhexkm4u/2/
However, I need the background to be white and border around this shape in purple and 1px. I was trying to fit the same shape just in white inside of this one, but everything got messy and didn't go as expected.
Maybe it is a wrong approach, but I want to end up with labels that would look something like this:
With CSS:
You can use CSS transforms on pseudo elements to create the background with a transparent inverted triangle at the bottom:
body{background:url('http://lorempixel.com/image_output/food-q-c-640-480-1.jpg');background-size:cover;}
p{
position: relative;
width: 150px; height: 150px;
overflow: hidden;
border-top:3px solid #EF0EFE;
}
p:before, p:after{
content: '';
position: absolute;
top: -3px;
height: 100%; width: 50%;
z-index: -1;
border:2px solid #EF0EFE;
box-sizing:border-box;
}
p:before{
left: 0;
transform-origin: 0 0;
transform: skewY(-20deg);
border-width:0 0 4px 3px;
}
p:after{
right: 0;
transform-origin: 100% 0;
transform: skewY(20deg);
border-width:0 3px 4px 0;
}
<p>Some text ... </p>
Note that you will need to add vendor prefixes on the transform and transform-origin properties to maximize browser support. See canIuse for more information.
With SVG
Another approach is to use an inline SVG with the polygon element:
body{background: url('http://lorempixel.com/image_output/food-q-c-640-480-1.jpg');background-size: cover;}
div{position: relative;width: 100px; height: 150px;}
svg{position: absolute;width: 100%;height: 100%;z-index: -1;}
<div>
<svg viewbox="-1.5 -1.5 103 153">
<polygon points="100 0, 100 100, 50 85, 0 100, 0 0" fill="transparent" stroke-width="3" stroke="#ef0efe"/>
</svg>
<p>Some text ... </p>
</div>
Here is a slightly different method using pseudo-elements and transform rotations to create an outlined banner like this:
This angled shape is created with position: absolute pseudo-elements, :before and :after:
The excess is cut off with overflow: hidden on the parent to form our banner:
The outline is created with box-shadow and the two angles are prevented from overlapping by pulling / pushing the x-axis by 46px — box-shadow: 46px 0 0 3px #000
Full Example
div {
height: 100px;
width: 100px;
margin: 100px auto;
position: relative;
overflow: hidden;
border: solid 3px #000;
border-bottom: none;
text-align: center;
}
div:before,
div:after {
content: '';
display: block;
height: 100%;
width: 200%;
transform: rotate(20deg);
box-shadow: 46px 0 0 3px #000;
position: absolute;
top: 1px;
right: -120%;
}
div:after {
transform: rotate(-20deg);
left: -120%;
box-shadow: -46px 0 0 3px #000;
}
<div>Text</div>
STOLEN FROM CSS-SHAPES
#flag {
width: 110px;
height: 56px;
padding-top: 15px;
position: relative;
background: red;
color: white;
font-size: 11px;
letter-spacing: 0.2em;
text-align: center;
text-transform: uppercase;
}
#flag:after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 0;
height: 0;
border-bottom: 13px solid #eee;
border-left: 55px solid transparent;
border-right: 55px solid transparent;
}
DEMO:
#flag {
width: 110px;
height: 56px;
padding-top: 15px;
position: relative;
background: red;
color: white;
font-size: 11px;
letter-spacing: 0.2em;
text-align: center;
text-transform: uppercase;
}
#flag:after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 0;
height: 0;
border-bottom: 13px solid #eee;
border-left: 55px solid transparent;
border-right: 55px solid transparent;
}
<div id="flag"></div>
My Approach
My approach uses skewed elements, and allows you to quickly position them to your needs.
div {
height: 100px;
width: 100px;
position: relative;
border-left: 10px solid tomato;
border-top: 10px solid tomato;
border-right: 10px solid tomato;
text-align: center;
line-height: 100px;
font-size: 30px;
}
div:before {
content: "";
position: absolute;
height: 50%;
width: 50%;
left: -10px; /*width of border*/
bottom: -30px;
z-index: -2;
-webkit-transform: skewY(-20deg);
transform: skewY(-20deg);
border-bottom: 10px solid tomato;
border-left: 10px solid tomato;
}
div:after {
content: "";
position: absolute;
height: 50%;
width: 50%;
right: -10px; /*width of border*/
bottom: -30px;
z-index: -2;
-webkit-transform: skewY(20deg);
transform: skewY(20deg);
border-bottom: 10px solid tomato;
border-right: 10px solid tomato;
}
div:hover, div:hover:before, div:hover:after{
background:lightgray;
}
<div>TEXT</div>
I've had a go at updating your CSS to create the effect you want:
.css-shapes {
height: 250px;
width: 0px;
border-left: 99px solid #f00fff;
border-right: 99px solid #f00fff;
border-bottom: 39px solid transparent;
position: relative
}
.n-shape {
height: 248px;
width: 0px;
border-left: 95px solid #ffffff;
border-right: 95px solid #ffffff;
border-bottom: 39px solid transparent;
position: absolute;
top: -6px;
right: -95px;
}
.top {
position: absolute;
top: 0px;
width: 198px;
height: 2px;
background-color: #f00fff;
left: -99px;
border-bottom: 1px solid #f00fff;
}
<div class="css-shapes">
<div class="n-shape"></div>
<div class="top"></div>
</div>
Fiddle: http://jsfiddle.net/dywhjwna/
Here is what I came up with.
Link Fiddle
It correspond to what you were looking for however I guess there should be a "better way" to it rather than playing with border.
HTML
<div id="text-div">
Text
</div>
<div id="pacman">
<div id="left-triangle"></div>
<div id="right-triangle"></div>
</div>
CSS
#text-div {
width: 118px;
height: 60px;
text-align: center;
border: 1px solid purple;
border-bottom: 0px;
line-height: 60px;
}
#pacman {
width: 0px;
height: 0px;
border-right: 60px solid purple;
border-top: 0px;
border-left: 60px solid purple;
border-bottom: 60px solid transparent;
}
#left-triangle{
position: relative;
left: -59px;
border-right: 58px solid transparent;
border-top: 0px;
border-left: 58px solid white;
border-bottom: 58px solid transparent;
}
#right-triangle{
position: relative;
top: -59px;
left: -57px;
border-right: 58px solid white;
border-top: 0px;
border-left: 58px solid transparent;
border-bottom: 58px solid transparent;
}
A quick workaround is to rotate it:
transform: rotate(90deg);
Fiddle
Another solution would be an SVG path, here's a fiddle!.
A better solution with text easily positioned in the middle, using a rectangle background and a triangle at the bottom.
.css-shapes{
position: relative;
height: 250px;
width: 150px;
background: #FFD05B;
color: #fff;
text-align: center;
line-height:225px;
font-size: 90px;
box-sizing: border-box;
}
.css-shapes:after{
content: '';
position:absolute;
left:0;
bottom: 0;
display: block;
width: 100%;
height:50px;
border-bottom: 25px solid #fff;
border-left: 75px solid transparent;
border-right: 75px solid transparent;
box-sizing: border-box;
}
<div class="css-shapes">1</div>
I've see a lot of threads remotely related that basically suggest CSS triangles in the ::after or ::before pseudos, but none have really panned out. I'm throwing this out to see if anyone has any ideas.
I'm looking to create a div with a pointed or pitched top that still maintains a uniform border and box-shadow with the rest of the div.
See link for an image of what I'm trying to create:
If you dont want to use a image you could do something like this. But working with an image is lot easier in this case.
body {
background-color: #CCC;
}
.wrapper {
}
.outer {
width: 0;
height: 0;
border-style: solid;
border-width: 0 205px 32px 205px;
border-color: transparent transparent #ffffff transparent;
position: absolute;
}
.inner {
width: 0;
height: 0;
border-style: solid;
border-width: 0 200px 32px 200px;
border-color: transparent transparent #ea2225 transparent;
margin-left: -200px;
margin-top: 5px;
position: absolute;
}
.fix {
background-color: #FFF;
height: 10px;
width: 410px;
position: absolute;
margin-top: 32px;
}
.red {
width: 396px;
height: 300px;
background-color: #ea2225;
margin-top: 37px;
position: absolute;
border-left: 7px solid #FFF;
border-right: 7px solid #FFF;
border-bottom: 6px solid #FFF;
-webkit-box-shadow: 3px 5px 5px 0px rgba(48,48,48,1);
-moz-box-shadow: 3px 5px 5px 0px rgba(48,48,48,1);
box-shadow: 3px 5px 5px 0px rgba(48,48,48,1);
}
<div class="wrapper">
<div class="fix"></div>
<div class="outer">
<div class="inner">
</div>
</div>
</div>
<div class="red"></div>
See http://jsfiddle.net/0csqog8s/
this should get you started:
Update
This is an updated fiddle which is much better presented.
.first {
display: inline-block;
width: 3em;
height: 3em
}
.second {
position: relative;
display: inline-block;
width: 3em;
height: 3em
}
.third {
position: absolute;
display: inline-block;
width: 0;
height: 0;
line-height: 0;
border: 1.5em solid transparent;
margin-top: -1em;
border-bottom: 1em solid #007BFF;
left: 0em;
top: 0em
}
.forth {
position: absolute;
display: inline-block;
width: 0;
height: 0;
line-height: 0;
border: 1.5em solid #007BFF;
border-bottom: 1.5em solid #007BFF;
left: 0em;
top: 1.5em
}
<span class="first"><span class="second"><i class="third"></i><i class="forth"></i></span></span>