I have an element with a known ID I can target. How could I create a bestseller-badge like this with css only? I cannot change the html.
I know how to create this but only if I could edit the html, which I cannot:
.box {
width: 200px; height: 300px;
position: relative;
border: 1px solid #BBB;
background: #EEE;
}
.ribbon {
position: absolute;
right: -5px; top: -5px;
z-index: 1;
overflow: hidden;
width: 75px; height: 75px;
text-align: right;
}
.ribbon span {
font-size: 10px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
width: 100px;
display: block;
background: #79A70A;
background: linear-gradient(#9BC90D 0%, #79A70A 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 19px; right: -21px;
}
.ribbon span::before {
content: "";
position: absolute; left: 0px; top: 100%;
z-index: -1;
border-left: 3px solid #79A70A;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #79A70A;
}
.ribbon span::after {
content: "";
position: absolute; right: 0px; top: 100%;
z-index: -1;
border-left: 3px solid transparent;
border-right: 3px solid #79A70A;
border-bottom: 3px solid transparent;
border-top: 3px solid #79A70A;
}
<div class="box">
<div class="ribbon"><span>Bestseller</span></div>
</div>
The thing is I only have the parent box and not the ribbon inside. I cant input html.
Because in pseudo elements you can't put any html markup, you need to get clever with just using simple shapes and combining them together. Additionally, you can't have multiple :after pseudo elements, so we are limited to just two shapes (one for :after and one for :before). The one in :after could be the bestseller front of the badge, with text. The trickiest part was to get the clip-path: polygon(...points) to get right so that we get the effect of trimmed ribbon. Fortunately, Firefox dev tools have a nifty polygon modification tool that was very helpful. Getting the two little corners that make the "wrap around" effect was a bit trickier, but putting it in a :before pseudo element with z-index: -1 and a little hand-tweaked offset did the trick. The end effect is below:
.box {
width: 200px; height: 300px;
position: relative;
border: 1px solid #BBB;
background: #EEE;
margin: 20px;
display: inline-block;
}
.bestseller:before {
content: "";
z-index: -1;
overflow: hidden;
transform: rotate(-135deg);
width: 120px;
display: block;
background: #79A70A;
background: linear-gradient(#9BC90D 0%, #79A70A 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 34px;
right: -16px;
clip-path: polygon(120px 20px, 90px -10px, 30px -10px, 0px 20px, 10px 30px, 110px 30px);
height: 20px;
width: 120px;
}
.bestseller:after {
content: "bestseller";
z-index: 1;
overflow: hidden;
font-size: 10px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(45deg);
width: 120px;
display: block;
background: #79A70A;
background: linear-gradient(#9BC90D 0%, #79A70A 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 20px; right: -30px;
clip-path: polygon(120px 20px, 90px -10px, 30px -10px, 0px 20px, 10px 30px, 110px 30px)
}
<div class="box">
</div>
<div class="box bestseller">
</div>
With the help of only CSS using pseudo class, we cannot create exactly the same but similar to that is possible. Add the id "ribbon" to div with class "box" and try with the below css. Increment/decrement the height, top right, etc based on the size of your div.
#ribbon:before {
content: "";
width: 60px;
display: block;
position: absolute;
top: 14px;
right: -28px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
border-left: 30px solid transparent;
border-right: 30px solid transparent;
border-bottom: 30px solid green;
height: 0;
}
#ribbon:after {
content: "Bestseller";
font-size: 10px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 30px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
width: 60px;
display: block;
position: absolute;
top: 14px;
right: 2px;
height: 30px;
}
Instead of trying with border for the background color of ribbon, you can also try using an ribbon image as background and use the text on top of it.
Related
I have a span which contains ellipses and i want to show the content through tooltip, but the position of the tooltip isn't seem to adjust as i can't apply position relative to the parent (due to ellipses). Here's the code i've tried
.data-tooltip:hover:before{
content: "";
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-bottom: 5px solid rgba(0, 0, 0, 0.6);
position: absolute;
bottom: 82%;
left: 25%;
-webkit-transform: translate(-58%, 41.5%);
transform: translate(-58%, 51.5%);
}
.data-tooltip:hover:after{
content: attr(data-title);
padding: 6px 8px;
color: #fff;
text-align: left;
text-decoration: none;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
min-height: 32px;
word-wrap: break-word;
position: absolute;
top: unset;
bottom: 75%;
-webkit-transform: translate(-50%, 50%);
transform: translate(-50%, 50%);
}
<span class="data-tooltip" data-tooltip="my tooltip">
ellipsed content
</span>
Here i am using 'before' for tooltip arrow and 'after' for tooltip content, but their positions doesn't seem to adjust either.
i have tried positioning my data-tooltip content relative, but due to overflow:hidden, the tooltip cuts outside the box.
An example below...
This code quoted from Chris Bracco. Please look at this article for detail.
/* Add this attribute to the element that needs a tooltip */
[data-tooltip] {
position: relative;
z-index: 2;
cursor: pointer;
}
/* Hide the tooltip content by default */
[data-tooltip]:before,
[data-tooltip]:after {
visibility: hidden;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=0);
opacity: 0;
pointer-events: none;
}
/* Position tooltip above the element */
[data-tooltip]:before {
position: absolute;
bottom: 150%;
left: 50%;
margin-bottom: 5px;
margin-left: -80px;
padding: 7px;
width: 160px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
background-color: #000;
background-color: hsla(0, 0%, 20%, 0.9);
color: #fff;
content: attr(data-tooltip);
text-align: center;
font-size: 14px;
line-height: 1.2;
}
/* Triangle hack to make tooltip look like a speech bubble */
[data-tooltip]:after {
position: absolute;
bottom: 150%;
left: 50%;
margin-left: -5px;
width: 0;
border-top: 5px solid #000;
border-top: 5px solid hsla(0, 0%, 20%, 0.9);
border-right: 5px solid transparent;
border-left: 5px solid transparent;
content: " ";
font-size: 0;
line-height: 0;
}
/* Show tooltip content on hover */
[data-tooltip]:hover:before,
[data-tooltip]:hover:after {
visibility: visible;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}
<p style="margin-top:50px">
<span data-tooltip="I’m the tooltip text.">I’m a span with a tooltip.</span>
</p>
Instead of
data-tooltip="my tooltip"
Your data-tooltip attribute should be data-title
That should work now.
I'm trying to design a button using only CSS, and no images. The issue is with the bottom-left and top-right corners, and I'm using a background-color to achieve this when the button is on a solid background color. The issue is when the background is not a solid color and you can see the corners, like in the demo below.
So, I'd like to come up with a universal way to code this button with just CSS and no images.
Thanks!
Here is a demo of the button →
Here is the HTML I have in my demo:
<div id="banner">
<div id="button-box">
<a class="btn-cornered btn-cornered-dark-bg" href="#"><span>Learn More</span></a>
</div>
</div>
And the CSS:
#banner {
background: url('https://d3vv6lp55qjaqc.cloudfront.net/items/2D1R0A0B1q031R1C2P26/Image%202017-11-07%20at%201.57.17%20PM.png?X-CloudApp-Visitor-Id=8b9380dd59b56afec49e5f1e289c6692&v=53edcac2') no-repeat center -420px;
background-size: cover;
display: block;
width: 100%;
height: 200px;
text-align: center;
}
#button-box {
padding: 50px 0;
}
/* Button */
.btn-cornered {
padding-left: 20px;
padding-right: 20px;
position: relative;
display: inline-block;
line-height: 53px;
text-align: center;
color: #fff;
font-size: 24px;
border: 1px solid #fff;
border-bottom-left-radius: 10px;
border-top-right-radius: 10px;
text-decoration: none;
}
.btn-cornered:before {
position: absolute;
left: -1px;
bottom: -1px;
content: "";
border-bottom: 11px solid #fff;
border-right: 11px solid transparent;
}
.btn-cornered:after {
position: absolute;
left: -2px;
bottom: -2px;
content: "";
border-bottom: 11px solid;
border-right: 11px solid transparent;
}
.btn-cornered span {
top: -2px;
left: -1px;
position: relative;
padding-right: 20px;
display: block;
-webkit-transition: all 0.3s ease-in;
transition: all 0.3s ease-in;
}
.btn-cornered span:before {
position: absolute;
content: "";
border-bottom: 11px solid transparent;
border-right: 11px solid #fff;
}
.btn-cornered span:after {
position: absolute;
content: "";
border-bottom: 11px solid transparent;
border-right: 11px solid;
}
/* Dark Background Styles */
.btn-cornered-dark-bg {
height: 53px;
}
.btn-cornered-dark-bg:after {
border-bottom-color: #000000;
}
.btn-cornered-dark-bg span {
max-width: none;
line-height: 58px;
font-size: 24px;
height: 53px;
width: calc(100% + 2px);
}
.btn-cornered-dark-bg span:before {
right: 1px;
top: 1px;
}
.btn-cornered-dark-bg span:after {
border-right-color: #000;
right: 0px;
top: 0px;
}
Here's an example using pseudo elements and an extra span that is skewed to make the angled corners. The trick is hiding the overflow on the button and, with a little finesse, correctly lining up the skewed borders from the span.
I'm not fully satisfied as it requires the extra span and seems a bit fragile when changing font sizes, but here it is:
*, *:before, *:after {
box-sizing: border-box;
}
body {
background: steelblue;
}
button {
background: transparent;
padding: 10px 20px;
position: relative;
border: none;
margin: 20px;
overflow: hidden;
color: white;
}
button::before {
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 15px;
right: 15px;
content: '';
border-left: 1px solid white;
border-top: 1px solid white;
}
button::after {
display: block;
position: absolute;
bottom: 0;
right: 0;
top: 15px;
left: 15px;
content: '';
border-right: 1px solid white;
border-bottom: 1px solid white;
}
button span {
display: block;
position: absolute;
z-index: -1;
top: 0;
right: -18px;
bottom: 0;
left: 15px;
border: 1px solid white;
transform: skew(45deg);
transform-origin: bottom left;
}
<button>
<span></span>
Sign up & Stay Connected
</button>
Clip-path solution
It is done by pseudo element after which is clipped using css3 clip-path to desired shape. However, clip-path is not supported by IE and Edge (Can I use). It can be little tricky to change values in clip-path to get desired width of border and length of "cutted triangle" so I create little script for that - Codepen
a {
position: relative;
padding: 8px 20px;
}
a::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
-webkit-clip-path: polygon(calc(100% - 2px) 11px, calc(100% - 2px) 100%, 100% 100%, 100% 10px, calc(100% - 10px) 0, 0% 0%, 0% calc(100% - 10px), 10px 100%, 100% 100%, 100% calc(100% - 2px), 11px calc(100% - 2px), 2px calc(100% - 11px), 2px 2px, calc(100% - 11px) 2px);
clip-path: polygon(calc(100% - 2px) 11px, calc(100% - 2px) 100%, 100% 100%, 100% 10px, calc(100% - 10px) 0, 0% 0%, 0% calc(100% - 10px), 10px 100%, 100% 100%, 100% calc(100% - 2px), 11px calc(100% - 2px), 2px calc(100% - 11px), 2px 2px, calc(100% - 11px) 2px);
}
Text Here
Demo - JS Bin
Thanks everyone for your solutions and suggestions. For what it's worth, this is the solution I came up.
CSS:
.abutton {
overflow: hidden;
position: relative;
z-index: 1;
padding: 10px 20px;
border: none;
background: transparent;
text-align: center;
line-height: 1;
font-size: 24px;
color: #fff;
display: inline-block;
text-decoration: none;
}
.abutton:before {
content: '';
display: block;
position: absolute;
top: 0;
right: 8px;
bottom: 8px;
left: 0;
border-left: 1px solid #ffffff;
}
.abutton:after {
content: '';
display: block;
position: absolute;
top: 8px;
right: 0;
bottom: 0;
left: 15px;
border-right: 1px solid #ffffff;
}
.abutton span {
width: 100%;
height: 100%;
display: block;
position: absolute;
z-index: -1;
top: 0;
left: 0;
}
.abutton span:before,.abutton span:after {
content: '';
width: 100%;
height: 100%;
display: block;
position: absolute;
-webkit-transform: skew(45deg);
transform: skew(45deg);
}
.abutton span:before {
left: 8px;
bottom: 0;
border-bottom: 1px solid #fff;
border-left: 1px solid #fff;
-webkit-transform-origin: bottom left;
transform-origin: bottom left;
}
.abutton span:after {
top: 0;
right: 8px;
border-top: 1px solid #fff;
border-right: 1px solid #fff;
-webkit-transform-origin: top right;
transform-origin: top right;
}
footer .abutton {
font-size: 21px;
}
.abutton:hover {
color: #666;
}
.abutton:hover span:before,.abutton:hover span:after {
background-color: #fff;
}
#button-frame {
background: #666;
min-height: 200px;
padding: 20px;
}
HTML:
<div id="button-frame">
<a class="abutton" href="#"><span></span>Learn More</a>
</div>
I am trying to use this ribbon code (found on some generator site)
link included
I think it looks nicev however it just doesn't fit the LONG line of text I need to display in there (PAST PRESIDENT).
This is the first time I'm trying to use a CSS ribbon effect.. and can not seem to wrap my head around what params will make move it over (to the left some)..and make it longer to display the longer text I want to display.
it's a right side justified ribbon (just to be clear).. that needs to be moved over to the left a little bit.. and made 'longer' to display longer text.
Here is my code:
/* CSS ribbon styles */
/* http://www.cssportal.com/css-ribbon-generator/ */
.ribbon {
position: absolute;
right: -5px; top: -5px;
z-index: 1;
overflow: hidden;
width: 75px; height: 75px;
text-align: right;
}
.ribbon span {
font-size: 10px;
font-weight: bold;
font-size:10px;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
width: 100px;
display: block;
background: #79A70A;
background: linear-gradient(#2989d8 0%, #1e5799 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 19px; right: -21px;
}
.ribbon span::before {
content: "";
position: absolute; left: 0px; top: 100%;
z-index: -1;
border-left: 3px solid #1e5799;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #1e5799;
}
.ribbon span::after {
content: "";
position: absolute; right: 0px; top: 100%;
z-index: -1;
border-left: 3px solid transparent;
border-right: 3px solid #1e5799;
border-bottom: 3px solid transparent;
border-top: 3px solid #1e5799;
}
While I made it somewhat bigger using these updated styles..
the font looks a little 'janky'
I cant seem to get the before/after effects to adjust now that I have adjusted the other styles.
Updated:
.ribbon {
position: absolute;
right: -5px; top: -5px;
z-index: 1;
overflow: hidden;
width: 275px;
height: 275px;
text-align: right;
}
/* new bigger attempt */
.ribbon span {
background: rgba(0, 0, 0, 0) linear-gradient(#2989d8 0%, #1e5799 100%) repeat scroll 0 0;
box-shadow: 0 3px 10px -5px rgb(0, 0, 0);
color: #fff;
display: block;
font-size: 10px;
font-weight: bold;
line-height: 20px;
position: absolute;
right: -85px;
text-align: center;
text-transform: uppercase;
top: 32px;
transform: rotate(45deg);
width: 250px;
}
Try this. I updated the width/height/top/left on .ribbon and top/right on .ribbon span.
.box {
width: 200px;
height: 200px;
background: gainsboro;
position: relative;
}
/* CSS ribbon styles */
/* http://www.cssportal.com/css-ribbon-generator/ */
.ribbon {
position: absolute;
right: -6px;
top: -5px;
z-index: 1;
overflow: hidden;
width: 115px;
height: 115px;
text-align: right;
}
.ribbon span {
font-weight: bold;
font-size: 10px;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
width: 125px;
display: block;
background: linear-gradient(#2989d8 0%, #1e5799 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 28px;
right: -24px;
}
.ribbon span::before {
content: "";
position: absolute;
left: 0px;
top: 100%;
z-index: -1;
border-left: 3px solid #1e5799;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #1e5799;
}
.ribbon span::after {
content: "";
position: absolute;
right: 0px;
top: 100%;
z-index: -1;
border-left: 3px solid transparent;
border-right: 3px solid #1e5799;
border-bottom: 3px solid transparent;
border-top: 3px solid #1e5799;
}
<div class="box">
<div class="ribbon"><span>PAST PRESIDENT</span></div>
</div>
I was experimenting some fancy CSS effects before apply to an ongoing application and I came across Ribbons.
By itself, it works perfectly but I wouldn't use a fixed element as suggested by the generator so I added an image to the main box
However, the images of the application in which I would be adding this feature are not of the same size yet, so I decided to change the old <img>for CSS background images and then make use of background-size property.
But sometimes the background image is overflowing the dimensions of box. It would be just a matter of add an overflow: hidden in #preview and everything would be solved, but if I do that the "curves" of the Ribbon disappear.
How could I change that? Here's the current test code, although for some reason the background is not loading, not in here nor in JSFiddle.
#preview {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
border: 3px solid #000;
display: block;
/*overflow: hidden;*/
perspective: 1000px;
position: relative;
height: 260px;
width: 365px;
}
.front {
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
background-image: url( 'https://photos.smugmug.com/Dog-Shows/BTB-September2013-Sunday/BTB-UKC-Alaskan-Klee-Kai/i-xFmLHS8/0/S/889_MG_6212a-889-S.jpg' );
}
.ribbon {
position: absolute;
left: -5px; top: -5px;
z-index: 1;
overflow: hidden;
width: 75px; height: 75px;
text-align: right;
}
.ribbon span {
font-size: 10px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
width: 100px;
display: block;
background: #79A70A;
background: linear-gradient(#F70505 0%, #8F0808 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 19px; left: -21px;
}
.ribbon span::before {
content: "";
position: absolute; left: 0px; top: 100%;
z-index: -1;
border-left: 3px solid #8F0808;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #8F0808;
}
.ribbon span::after {
content: "";
position: absolute; right: 0px; top: 100%;
z-index: -1;
border-left: 3px solid transparent;
border-right: 3px solid #8F0808;
border-bottom: 3px solid transparent;
border-top: 3px solid #8F0808;
}
<div id="preview">
<div class="ribbon">
<span>POPULAR</span>
</div>
<div class="front"></div>
</div>
The image goes to .front because I also intend to use David Walsh's Card Fliping technique, which is already working in parallel and I believe is not relevant to the case.
Even setting background-size to containmade the image overflow, but this value is not desirable as it won't cover like the currentlt defined value.
.front is just a text container. you need to apply background image to #preview
#preview {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
border: 3px solid #000;
display: block;
/*overflow: hidden;*/
perspective: 1000px;
position: relative;
height: 260px;
width: 365px;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
background-image: url( 'https://photos.smugmug.com/Dog-Shows/BTB-September2013-Sunday/BTB-UKC-Alaskan-Klee-Kai/i-xFmLHS8/0/S/889_MG_6212a-889-S.jpg' );
}
.front {
color: white;
}
.ribbon {
position: absolute;
left: -5px; top: -5px;
z-index: 1;
overflow: hidden;
width: 75px; height: 75px;
text-align: right;
}
.ribbon span {
font-size: 10px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
width: 100px;
display: block;
background: #79A70A;
background: linear-gradient(#F70505 0%, #8F0808 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 19px; left: -21px;
}
.ribbon span::before {
content: "";
position: absolute; left: 0px; top: 100%;
z-index: -1;
border-left: 3px solid #8F0808;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #8F0808;
}
.ribbon span::after {
content: "";
position: absolute; right: 0px; top: 100%;
z-index: -1;
border-left: 3px solid transparent;
border-right: 3px solid #8F0808;
border-bottom: 3px solid transparent;
border-top: 3px solid #8F0808;
}
<div id="preview">
<div class="ribbon">
<span>POPULAR</span>
</div>
<div class="front">FRONT DIV Lorem ipsum la-la-la</div>
</div>
Or you need to define width and height for .front:
#preview {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
border: 3px solid #000;
display: block;
/*overflow: hidden;*/
perspective: 1000px;
position: relative;
height: 260px;
width: 365px;
}
.front {
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
background-image: url( 'https://photos.smugmug.com/Dog-Shows/BTB-September2013-Sunday/BTB-UKC-Alaskan-Klee-Kai/i-xFmLHS8/0/S/889_MG_6212a-889-S.jpg' );
height: 260px;
width: 365px;
}
.ribbon {
position: absolute;
left: -8px; top: -8px;
z-index: 1;
overflow: hidden;
width: 75px; height: 75px;
text-align: right;
}
.ribbon span {
font-size: 10px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
width: 100px;
display: block;
background: #79A70A;
background: linear-gradient(#F70505 0%, #8F0808 100%);
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
position: absolute;
top: 19px; left: -21px;
}
.ribbon span::before {
content: "";
position: absolute; left: 0px; top: 100%;
z-index: -1;
border-left: 3px solid #8F0808;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #8F0808;
}
.ribbon span::after {
content: "";
position: absolute; right: 0px; top: 100%;
z-index: -1;
border-left: 3px solid transparent;
border-right: 3px solid #8F0808;
border-bottom: 3px solid transparent;
border-top: 3px solid #8F0808;
}
<div id="preview">
<div class="ribbon">
<span>POPULAR</span>
</div>
<div class="front"></div>
</div>
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>