html/css: how to create a hexagonal image-placeholder - html

This is (almost) what I want to create:
HTML
<div class="hexagon1">
<div class="hexagon-in1">
<div class="hexagon-in2">
</div>
</div>
</div>
CSS
.hexagon1 {
overflow: hidden;
visibility: hidden;
-webkit-transform: rotate(120deg);
-moz-transform: rotate(120deg);
-ms-transform: rotate(120deg);
-o-transform: rotate(120deg);
transform: rotate(120deg);
width: 400px;
height: 200px;
margin: 0 0 0 -80px;
}
.hexagon-in1 {
overflow: hidden;
width: 100%;
height: 100%;
-webkit-transform: rotate(-60deg);
-moz-transform: rotate(-60deg);
-ms-transform: rotate(-60deg);
-o-transform: rotate(-60deg);
transform: rotate(-60deg);
}
.hexagon-in2 {
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: 50%;
background-image: url(http://placekitten.com/240/240);
visibility: visible;
-webkit-transform: rotate(-60deg);
-moz-transform: rotate(-60deg);
-ms-transform: rotate(-60deg);
-o-transform: rotate(-60deg);
transform: rotate(-60deg);
}
The problem is, that I need a border on the hexagon and if possible I would like to place the picture inside an img-tag. I tried adding the border on either div but I only got a border on top and bottom of the hexagon because of the visibility-hidden or the overflow-hidden attribute.
This is what I've found so far while googling:
http://csshexagon.com/
https://www.queness.com/post/13901/create-beautiful-hexagon-shapes-with-pure-css3
https://github.com/web-tiki/responsive-grid-of-hexagons
I've also found some questions concerning this matter here on Stackoverflow but neither of them explained how exactly you could create a hexagon. Also the hexagons in the examples are all standing on an edge, which is not what I want (as demonstrated in the code). I only need one hexagon and not a grid as well.
When I tried to change the styles of the examples it always ended in a desastrous chaos. This is why I would like to know how to create and to calculate the divs which are used to create a hexagon with border and a picture inside.
Which rate does the width have to the height?
How can I create a border that has the same width on each side?
Where do I have to place the picture as background-image?
How big should the picture be (in percentage to the divs)?
What transformations do you really need to create the hexagon? (I saw an example which used scale, rotate and translate to get a picture inside)
How can the rotation be calculated?
How do I calculate the margin needed?
As I am quite the novice in web-designing can someone explain this as simple as possible? It would suffice if someone can show me according to the example-code above how the numbers are calculated. I know that a hexagon has an inner angle of 120° and that's about it.
Thanks for your help in anticipation. :)
EDIT
Another page I found about hexagons but only to create the shape and not really putting either an image in it nor having a border around it:
http://jtauber.github.io/articles/css-hexagon.html

I will refer you to go with SVG approach to create this shape. Its really easy and also if you are considering a responsive web layout it can be achieved with this easily.
Reason for this approach -
1. You donot have to write much css.
2. Inline SVG is the modern web approach .
3. Scalable and durable.
4. Responsive
The polygon tag in the svg makes the shape that you want and with the css we can target the things we want to achieve like border in this case. Image has been linked using pattern.
Below is the snippet with example of what you need.
svg {
width: 30%;
margin: 0 auto;
}
#hex {
stroke-width: 2;
stroke: red;
}
<svg viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://dummyimage.com/600x400/red/fff" x="-25" width="150" height="100" />
</pattern>
</defs>
<polygon id="hex" points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img)"/>
</svg>
<svg viewbox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://farm4.staticflickr.com/3165/5733278274_2626612c70.jpg" x="-40" width="150" height="100" />
</pattern>
</defs>
<polygon id="hex" points="25 8 75 8 100 50 75 92 25 92 0 50" fill="url(#img)" />
</svg>

Important Note
Be informed that this solution does not work for those who want to create something similar supported by all browsers as for the time being IE does not support the clip-path-property used in this example!!
I've found a way to do it thanks to #SahilDhir although it's more of a workaround:
HTML
<div class="poligon">
<img src="http://lorempixel.com/g/600/400/">
</div>
CSS
.poligon {
display: inline-block;
position: relative;
width: 200px;
height: 180px;
background: red;
box-sizing: border-box;
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
.poligon img {
position: absolute;
top: 2px; /* equal to border thickness */
left: 2px; /* equal to border thickness */
width: 196px; /* container height - (border thickness * 2) */
height: 176px; /* container height - (border thickness * 2) */
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
Note that I did not calculate much here, but rather tried achieving a six-sided figure.
I will have the problem that my picture will have a transparent background, but I thought that I might produce a linear gradient to fill the background polygon. I will have to try that out first though ^^
I will not mark this as the final answer as my questions have not yet been answered truly. I still want to be able to create a hexagon as the one in the example I gave above where I would be able to adapt the heights and widths as well as the border thicknesses the way I want.
EDIT
As I did not find a better solution I have improved the one here and figured out the calculations needed:
HTML
<div class="poligon">
<div class="hex-background">
<img src="https://img.clipartfest.com/953d8641fe933437bbc41d48e6fc8492_yellow20stars20clipart-christmas-stars-clipart-without-background_532-506.png">
</div>
</div>
CSS
.poligon {
display: inline-block;
position: relative;
width: 120px;
height: 103.92px; /* width * 0.866 */
background: red;
box-sizing: border-box;
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
.hex-background {
position: absolute;
background-color: white;
top: 2px; /* equal to border thickness */
left: 2px; /* equal to border thickness */
width: 116px; /* container width - (border thickness * 2) */
height: 99.92px; /* container height - (border thickness * 2) */
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
.poligon img {
position: absolute;
width: 116px; /* container width - (border thickness * 2) */
height: 99.92px; /* container height - (border thickness * 2) */
-webkit-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
-moz-clip-path: polygon(0% 50%, 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%);
}
The clip-path part is correct if you want a same-sided hexagon.
With the picture above you can see how I found those numbers ;) If you have further questions about this, don't hesitate to ask. I'll try to explain it the best I can.

I needed something similar, and the easiest way to do it is with two hexagons, one on top of the other.
Using the shapes provided by The Shapes of CSS:
#hexagon1 {
width: 100px;
height: 55px;
background: red;
position: absolute;
z-index: 2;
}
#hexagon1:before {
content: "";
position: absolute;
top: -25px;
left: 0;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 25px solid red;
}
#hexagon1:after {
content: "";
position: absolute;
bottom: -25px;
left: 0;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-top: 25px solid red;
}
#hexagon2 {
width: 101px;
height: 56px;
background: black;
position: relative;
z-index: 1;
}
#hexagon2:before {
content: "";
position: absolute;
top: -26px;
left: 0;
width: 0;
height: 0;
border-left: 51px solid transparent;
border-right: 51px solid transparent;
border-bottom: 26px solid black;
}
#hexagon2:after {
content: "";
position: absolute;
bottom: -26px;
left: 0;
width: 0;
height: 0;
border-left: 51px solid transparent;
border-right: 51px solid transparent;
border-top: 26px solid black;
}
Here's a CodePen I made for you: http://codepen.io/vogelbeere/pen/peYjNe

Related

Positioning clipping paths to div corners [duplicate]

I'm wondering if it's possible in CSS to make a border but only for corner. Something like this:
**** ****
* *
* *
CONTENT
* *
* *
**** ****
You can achieve that using multiple linear gradients as a background image.
div {
width: 100px;
height: 100px;
background:
linear-gradient(to right, black 4px, transparent 4px) 0 0,
linear-gradient(to right, black 4px, transparent 4px) 0 100%,
linear-gradient(to left, black 4px, transparent 4px) 100% 0,
linear-gradient(to left, black 4px, transparent 4px) 100% 100%,
linear-gradient(to bottom, black 4px, transparent 4px) 0 0,
linear-gradient(to bottom, black 4px, transparent 4px) 100% 0,
linear-gradient(to top, black 4px, transparent 4px) 0 100%,
linear-gradient(to top, black 4px, transparent 4px) 100% 100%;
background-repeat: no-repeat;
background-size: 20px 20px;
}
<div></div>
Assuming <div id="content">CONTENT</div> and that CONTENT includes at least one HTML node.
#content {position:relative}
#content:before, #content:after, #content>:first-child:before, #content>:first-child:after {
position:absolute; content:' ';
width:80px; height: 80px;
border-color:red; /* or whatever colour */
border-style:solid; /* or whatever style */
}
#content:before {top:0;left:0;border-width: 1px 0 0 1px}
#content:after {top:0;right:0;border-width: 1px 1px 0 0}
#content>:first-child:before {bottom:0;right:0;border-width: 0 1px 1px 0}
#content>:first-child:after {bottom:0;left:0;border-width: 0 0 1px 1px}
Here's a Fiddle
I would use overlapping divs.
One with square corners.
And the Other with rounded corner (so it doesn't hide the corners of the first one).
#div1 {
position:absolute;
top:9px;
left:9px;
height:100px;
width:100px;
background-color:white;
border:1px solid black;
}
#div2 {
position:relative;
top:-1px;
left:-1px;
height:102px;
width:102px;
background-color:white;
border-radius: 15px;
}
<div id="div1" />
<div id="div2" />
Result:
An enhanced solution provided by #web-tiki:
http://jsfiddle.net/webtiki/y3EfP/147/
Here is an idea using gradient and CSS variables where you can easily control the shape of your border:
.box {
--b: 5px; /* thickness of the border */
--c: red; /* color of the border */
--w: 20px; /* width of border */
border: var(--b) solid #0000; /* space for the border */
--_g: #0000 90deg,var(--c) 0;
--_p: var(--w) var(--w) border-box no-repeat;
background:
conic-gradient(from 90deg at top var(--b) left var(--b),var(--_g)) 0 0 / var(--_p),
conic-gradient(from 180deg at top var(--b) right var(--b),var(--_g)) 100% 0 / var(--_p),
conic-gradient(from 0deg at bottom var(--b) left var(--b),var(--_g)) 0 100% / var(--_p),
conic-gradient(from -90deg at bottom var(--b) right var(--b),var(--_g)) 100% 100% / var(--_p);
/*Irrelevant code*/
width:200px;
height:100px;
box-sizing:border-box;
margin:5px;
display:inline-flex;
font-size:30px;
justify-content:center;
align-items:center;
text-align:center;
}
<div class="box">
some content
</div>
<div class="box" style="--c:blue;--w:40px;--b:2px">
some content
</div>
<div class="box" style="--c:green;--w:30%;--b:8px">
some content
</div>
<div class="box" style="--c:black;--w:50%;--b:3px">
some content
</div>
<div class="box" style="--c:purple;--w:10px;--b:10px">
some content
</div>
<div class="box" style="--c:orange;--w:calc(50% - 10px);--b:4px">
some content
</div>
You can also have a complex coloration if you combine this with mask:
.box {
--b: 5px; /* thickness of the border */
--c: red; /* color of the border */
--w: 20px; /* width of border */
padding: var(--b); /* space for the border */
position:relative;
/*Irrelevant code*/
width:200px;
height:100px;
box-sizing:border-box;
margin:5px;
display:inline-flex;
font-size:30px;
justify-content:center;
align-items:center;
text-align:center;
}
.box::before {
content :"";
position: absolute;
inset: 0;
background: var(--c,red);
--_g: #0000 90deg,#000 0;
--_p: var(--w) var(--w) no-repeat;
--mask:
conic-gradient(from 90deg at top var(--b) left var(--b),var(--_g)) 0 0 / var(--_p),
conic-gradient(from 180deg at top var(--b) right var(--b),var(--_g)) 100% 0 / var(--_p),
conic-gradient(from 0deg at bottom var(--b) left var(--b),var(--_g)) 0 100% / var(--_p),
conic-gradient(from -90deg at bottom var(--b) right var(--b),var(--_g)) 100% 100% / var(--_p);
-webkit-mask: var(--mask);
mask: var(--mask);
}
<div class="box">
some content
</div>
<div class="box" style="--c:repeating-linear-gradient(45deg,red,blue);--w:40px;--b:2px">
some content
</div>
<div class="box" style="--c:repeating-linear-gradient(90deg,#000 0 5px,transparent 5px 10px);--w:30%;--b:8px">
some content
</div>
<div class="box" style="--c:conic-gradient(red,green,yellow);--w:50%;--b:3px">
some content
</div>
<div class="box" style="--c:purple;--w:10px;--b:10px">
some content
</div>
<div class="box" style="--c:repeating-linear-gradient(45deg,orange 0 5px,blue 5px 10px);--w:calc(50% - 10px);--b:4px">
some content
</div>
And why not with radius:
.box {
--b: 5px; /* thickness of the border */
--c: red; /* color of the border */
--w: 20px; /* width of border */
--r: 25px; /* radius */
padding: var(--b); /* space for the border */
position:relative;
/*Irrelevant code*/
width:200px;
height:100px;
box-sizing:border-box;
margin:5px;
display:inline-flex;
font-size:30px;
justify-content:center;
align-items:center;
text-align:center;
}
.box::before {
content: "";
position: absolute;
inset: 0;
background: var(--c,red);
padding: var(--b);
border-radius: var(--r);
-webkit-mask:
linear-gradient( 0deg,#000 calc(2*var(--b)),#0000 0) 50% var(--b)/calc(100% - 2*var(--w)) 100% repeat-y,
linear-gradient(-90deg,#000 calc(2*var(--b)),#0000 0) var(--b) 50%/100% calc(100% - 2*var(--w)) repeat-x,
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: destination-out;
mask-composite: exclude;
}
<div class="box">
some content
</div>
<div class="box" style="--c:repeating-linear-gradient(45deg,red,blue);--w:40px;--b:2px;--r:40px;">
some content
</div>
<div class="box" style="--c:repeating-linear-gradient(90deg,#000 0 5px,transparent 5px 10px);--w:30%;--b:8px">
some content
</div>
<div class="box" style="--c:conic-gradient(red,green,yellow);--w:50%;--b:3px">
some content
</div>
<div class="box" style="--c:purple;--w:10px;--b:10px;--r:0px">
some content
</div>
<div class="box" style="--c:repeating-linear-gradient(45deg,orange 0 5px,blue 5px 10px);--w:calc(50% - 10px);--b:4px;--r:10px">
some content
</div>
SVG
This is another great alternative if you now want to start using vectors to allow for great responsiveness.
<svg viewBox="0 0 100 100" width="50px">
<path d="M25,2 L2,2 L2,25" fill="none" stroke="black" stroke-width="3" />
<path d="M2,75 L2,98 L25,98" fill="none" stroke="black" stroke-width="3" />
<path d="M75,98 L98,98 L98,75" fill="none" stroke="black" stroke-width="3" />
<path d="M98,25 L98,2 L75,2" fill="none" stroke="black" stroke-width="3" />
</svg>
SVG is a great tool to use. Some of the advantages of using SVG in this case are:
Curve control
Fill control (opacity, color)
Stroke control (width, opacity, color)
Amount of code
Time to build and maintain the shape
Scalable
No HTTP request (if used inline like in the example)
Browser support for inline SVG goes back to Internet Explorer 9. See canIuse for more information.
You could absolutely position four <div>s, one in each corner, each with the appropriate two borders.
.corners {
position: relative;
width: 50px; /* for demo purposes */
padding: 10px;
}
.top, .bottom {
position: absolute;
width: 20px;
height: 20px;
pointer-events: none;
}
.top {
top: 0;
border-top: 1px solid;
}
.bottom {
bottom: 0;
border-bottom: 1px solid;
}
.left {
left: 0;
border-left: 1px solid;
}
.right {
right: 0;
border-right: 1px solid;
}
<div class="corners">
<div class="top left"></div>
<div class="top right"></div>
<div class="bottom right"></div>
<div class="bottom left"></div>
content goes here
</div>
Here are a couple of methods to create this effect without using any extra pseudo/real elements. One thing to note is that both these approaches would work only in modern browsers because they use CSS3 properties.
Using border-image: The border-image property makes it pretty easy to create such effects. The approach is as follows:
Create a transparent image which has borders just in the corner like here.
Set this image as the border-image-source and let the browser take care of the rest :) Since the default value for border-image-repeat is stretch, the browser would stretch the original image to fit the container even if the container becomes large.
The value set for the border-image-width property determines how thick the borders are.
.bordered {
background-color: beige;
border-image-source: url("http://i.stack.imgur.com/s2CAw.png");
border-image-slice: 1;
border-image-width: 5px;
}
.square {
height: 150px;
width: 150px;
}
.large-square {
height: 350px;
width: 350px;
}
/* Just for demo */
div {
margin-bottom: 10px;
}
<div class='bordered square'></div>
<div class='bordered large-square'></div>
Advantages:
Needs no extra elements (pseudo or real) which means less cluttered markup, pseudo elements can be used for other needs.
Is reasonably responsive. That is browser will adapt the borders even if container's dimensions change.
Drawbacks:
Relatively lower browser support. If IE10- support is needed then this is a no-go.
Since the border image is getting stretched, if the original image's canvas is a square and the container is a rectangle then the borders would look wider at top and bottom than left and right.
.bordered {
background-color: beige;
border-image-source: url("http://i.stack.imgur.com/s2CAw.png");
border-image-slice: 2;
border-image-width: 5px;
}
.small-square {
height: 75px;
width: 75px;
}
.square {
height: 150px;
width: 150px;
}
.large-square {
height: 350px;
width: 350px;
}
.rectangle {
height: 150px;
width: 250px;
}
.large-rectangle {
height: 150px;
width: 350px;
}
/* Just for demo */
div {
margin-bottom: 10px;
}
<div class='bordered small-square'></div>
<div class='bordered square'></div>
<div class='bordered large-square'></div>
<div class='bordered rectangle'></div>
<div class='bordered large-rectangle'></div>
Using background-image: The background-image property can also be used with linear-gradient images to produce the effect. The approach is as follows:
Create four linear-gradient images (two for top, bottom and two for left, right). These gradients would start with required color and continue to be that color for as many pixels as the width/height of the border image. After that it should be transparent.
For top and bottom borders, gradient's direction should be to right. For left and right borders, it should be to bottom.
The background-size value determines the thickness of the border. For top and bottom borders, the size of the gradient image would be 100% in X-axis and 5px (thickness) in Y-axis. For left and right borders, the size would 5px (thickness) in X-axis and 100% in Y-axis.
The background-repeat should be set to repeat-x for the top, bottom borders and to repeat-y for left and right borders.
The background-position is set to (-1 * half the size of the color in gradient) in the X or Y-axis as appropriate. This is to make half of the colored area appear on one side of the element while the other half appears on the other side (because gradient is repeating).
.bordered.square {
height: 150px;
width: 150px;
}
.bordered.rectangle {
height: 150px;
width: 250px;
}
.bordered {
background-color: beige;
background-image: linear-gradient(to right, black 30px, transparent 30px), linear-gradient(to right, black 30px, transparent 30px), linear-gradient(to bottom, black 30px, transparent 30px), linear-gradient(to bottom, black 30px, transparent 30px);
background-size: 100% 5px, 100% 5px, 5px 100%, 5px 100%;
background-position: -15px 0%, -15px 100%, 0% -15px, 100% -15px;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
}
/* Just for demo */
div {
margin-bottom: 10px;
}
<div class='bordered square'></div>
<div class='bordered rectangle'></div>
Advantages:
Needs no extra elements (pseudo or real) which means less cluttered markup, pseudo elements can be used for other needs.
Is reasonably responsive as the width of the color in gradient is fixed. If the width of the borders dashes need to change according to the container's dimensions then we can change the pixels value in gradient to percentage (with a few more minor changes) like in below snippet.
.bordered.square {
height: 150px;
width: 150px;
}
.bordered.large-square {
height: 250px;
width: 250px;
}
.bordered {
background-color: beige;
background-image: linear-gradient(to right, black 10%, transparent 10%), linear-gradient(to right, black 10%, transparent 10%), linear-gradient(to bottom, black 10%, transparent 10%), linear-gradient(to bottom, black 10%, transparent 10%);
background-size: 90% 5px, 90% 5px, 5px 90%, 5px 90%;
background-position: 0% 0%, 0% 100%, 0% 0%, 100% 0%;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
}
/* Just for demo */
div {
margin-bottom: 10px;
}
<div class='bordered square'></div>
<div class='bordered large-square'></div>
Drawbacks:
Relatively better browser support. If IE9- support is needed then this is a no-go.
If percentage based gradient is used then the same drawback with rectangles as mentioned for border-image would be applicable here also.
clip-path
Using two div's on top of each other.
And adding a clip-path to div that is in the back you can create a border like effect.
.wrapper {
display: inline-block;
background-color: black;
line-height: 0px;
-webkit-clip-path: polygon(0% 100%, 30% 100%, 30% 70%, 70% 70%, 70% 100%, 100% 100%, 100% 70%, 70% 70%, 70% 30%, 100% 30%, 100% 0%, 70% 0%, 70% 30%, 30% 30%, 30% 0%, 0% 0%, 0% 30%, 30% 30%, 30% 70%, 0% 70%);
clip-path: polygon(0% 100%,
30% 100%,
30% 70%,
70% 70%,
70% 100%,
100% 100%,
100% 70%,
70% 70%,
70% 30%,
100% 30%,
100% 0%,
70% 0%,
70% 30%,
30% 30%,
30% 0%,
0% 0%,
0% 30%,
30% 30%,
30% 70%,
0% 70%);
}
.wrapper {} .wrapper div {
display: inline-block;
height: 150px;
width: 150px;
margin: 10px;
background-color: white;
}
<div class="wrapper">
<div></div>
</div>
two pseudo elements
Using two large pseudo elements you can create the border effect.
.cut-border {
position: relative;
display: inline-block;
border: 5px solid black;
width: 150px;
height: 150px;
}
.cut-border::before {
content: "";
position: absolute;
height: calc(100% + 10px);
width: 50%;
background-color: white;
top: -5px;
left: 25%;
}
.cut-border::after {
content: "";
position: absolute;
height: 50%;
width: calc(100% + 10px);
background-color: white;
top: 25%;
left: -5px;
}
<div class="cut-border"></div>
An option that no one has mentioned so far is using multiple box-shadow to simulate that type of border. You would need one box-shadow for each corner:
div {
width: 150px;
height: 150px;
padding: 10px;
box-shadow:
-80px -80px 0 -70px black,
80px -80px 0 -70px black,
-80px 80px 0 -70px black,
80px 80px 0 -70px black;
}
<div>I am a box with borders only in the corners.</div>
It works by having four shadows (top-left, top-right, bottom-right, bottom-left) and reducing their size with a negative spread-radius (blur-radius will remain as zero):
box-shadow: offset-x offset-y [blur-radius] [spread-radius] [color];
While this is will work (even on IE!) and it is a simple method (no need for additional elements or pseudo-elements), it has two big shortfalls:
You need to know the size of the box to adjust the values of the box-shadow accordingly (or at least have a general idea to adjust the values of the shadows, because they don't accept percentages).
The corners will not be exactly squared. Instead, they will be proportional to the box size. This could be avoided by using 8 shadows instead of 4, but things get messy then.
In the end, using background gradients may be a better option and provides "more control" because it is all within the box. It could be achieved just with 4 linear-gradients (some answers indicate 8):
div {
--size: 32px;
width: 100px;
height: 100px;
padding: 10px;
background:
linear-gradient(blue var(--size), transparent 0 calc(100% - var(--size)), blue 0) 0 0 / 4px 100%,
linear-gradient(blue var(--size), transparent 0 calc(100% - var(--size)), blue 0) 100% 0 / 4px 100%,
linear-gradient(to right, blue var(--size), transparent 0 calc(100% - var(--size)), blue 0) 0 0 / 100% 4px,
linear-gradient(to right, blue var(--size), transparent 0 calc(100% - var(--size)), blue 0) 0 100% / 100% 4px
;
background-repeat: no-repeat;
}
<div>I am a box with borders only in the corners.</div>
I found this question, but I was not satisfied with the border-radius approach: As I was using more thick borders, the effect was not as good as I wanted to. I managed to create another solution, without images, and without any extra markup:
.box {
/* fake border */
position: relative;
overflow: hidden;
box-shadow: inset 0px 0px 0px 10px green;
padding: 1em;
}
.box:before {
/* this element will hide the fake border on the top and bottom */
content:'';
display: block;
position: absolute;
border-top:10px solid white;
border-bottom:10px solid white;
/* height = border-width x2 */
height:calc(100% - 20px);
top:0;
/* width = size of fake-border x2 */
width: calc(100% - 36px);
/* left = size of fake-border */
left:18px;
}
.box:after {
/* this element will hide the fake border on the left and right */
/* the rules for width, heigth, top and left will be the opposite of the former element */
display: block;
position: absolute;
content:'';
border-right:10px solid white;
border-left:10px solid white;
height:calc(100% - 36px);
width: calc(100% - 20px);
top:18px;
left: 0;
}
Here's a JSFiddle with this example: https://jsfiddle.net/t6dbmq3e/
Hope it helps.
Here is something that i did recently with content centred both vertically and horizontally.
The HTML
<div class="column">
<div class="c-frame-wrapper">
<div class="c-frame-tl"></div>
<div class="c-frame-tr"></div>
<div class="c-frame-br"></div>
<div class="c-frame-bl"></div>
<div class="c-frame-content">
© Copyright 2015 - Company name<br /><br />
St Winifrids St,<br />
The Saints, Harrogate HG1 5PZ, UK<br />
</div>
</div>
</div>
The CSS
.c-frame-wrapper {
width: 250px;
height: 100px;
font-size:11px;
color: $dark-grey-lighten-70;
/* center align x axis */
right: auto;
left: 50%;
transform: translateX(-50%);
}
.c-frame-tl {
top: 0;
left: 0;
position: absolute;
width:10px;
height:10px;
border-width: 3px;
border-style: solid none none solid;
border-color: #eb0000;
}
.c-frame-tr {
top: 0;
right: 0;
position: absolute;
width:10px;
height:10px;
border-width: 3px;
border-style: solid solid none none;
border-color: #eb0000;
}
.c-frame-br {
bottom: 0;
right: 0;
position: absolute;
width:10px;
height:10px;
border-width: 3px;
border-style: none solid solid none;
border-color: #eb0000;
}
.c-frame-bl {
bottom: 0;
left: 0;
position: absolute;
width:10px;
height:10px;
border-width: 3px;
border-style: none none solid solid;
border-color: #eb0000;
}
.c-frame-content {
width:100%;
text-align: center;
/*center alignment x and y*/
position: absolute;
top: 50%;
left: 50%;
bottom: auto;
right: auto;
transform: translate(-50%,-50%);
}
JSFiddle
i think the best solution is the pseudo element method. Nice and clean and doesn't pollute the html with (too many) extra elements.
I created this sass mixin using the code above, for a copy&paste solution:
#mixin corner-borders($corner-width: 1px, $corner-size: 5px, $color-border: grey, $color-background: white) {
position: relative;
border: $corner-width solid $color-border;
background-color: $color-background;
&::before {
content: "";
z-index: 0;
position: absolute;
top: -$corner-width;
bottom: -$corner-width;
left: $corner-size;
right: $corner-size;
background-color: $color-background;
}
&::after {
content: "";
z-index: 0;
position: absolute;
top: $corner-size;
bottom: $corner-size;
left: -$corner-width;
right: -$corner-width;
background-color: $color-background;
}
}
Then you can use it like this:
html:
<div class="border">
<div class="content">
Content
</div>
</div>
SCSS
.border {
#include corner-borders;
}
.content {
position: relative;
z-index: 1;
}
You need the z-index & relative position in there so the content sits on top of the pseudo elements.
I made a codepen demo here: http://codepen.io/timrross/pen/XMwVbV
I took Majid Laissi's answer and modified to be more understandable, simple and easy to modify.
img{
width:70px;
height:70px;
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
.custom-corners {
position: relative;
width: 150px;
height: 150px;
background-color: white;
border: 1px solid black;
}
.custom-corners:before {
content: '';
position: absolute;
top: -1px;
left: -1px;
border: 1px solid #fff;
height: 100%;
width: 100%;
border-radius: 10%;
}
.custom-corners:after {
content: '';
position: absolute;
bottom: -1px;
right: -1px;
border: 1px solid #fff;
height: 100%;
width: 100%;
border-radius: 10%;
}
<div class="custom-corners">
<img src="https://cdn.logo.com/hotlink-ok/logo-social-sq.png" alt="">
</div>
Ok as i suck in CSS i think i'll not be able to do it myself but i do that and it seems work :
<div id="half" style="position:absolute; top:0; left:0; width:30px; height:30px; overflow:visible; border-top:3px solid #F00; border-left:3px solid #06F;"></div>
<div id="half" style="position:absolute; bottom:0; right:0; width:30px; height:30px; overflow:visible; border-bottom:3px solid #F00; border-right:3px solid #06F;"></div>
And it seems to be working ;-) Sorry for disturb and thanks for your help.
There is no clean css way to just give the corners a border, but you could try to mimic the effect. Something like this perhaps: http://jsfiddle.net/RLG4z/
<div id="corners">
<div id="content">
content
</div>
</div>
#corners {
width: 200px;
height: 50px;
border-radius: 10px;
background-color: red;
margin: 10px;
}
#content {
background-color: white;
border-radius: 15px;
height: 30px;
padding: 10px;
}
due to the difference in border radius, the background color of the underlying div shows trough, giving the effect of a border on the corners.
Personally I think i would work with background images to achieve this, for better controle of the result.
This is your picture:
HTML:
<div class="shell">
<div class="top">
<div class="clear">
<div class="left">
****
</div>
<div class="right">
****
</div>
</div>
<div class="clear">
<div class="left">
*
</div>
<div class="right">
*
</div>
</div>
<div class="clear">
<div class="left">
*
</div>
<div class="right">
*
</div>
</div>
</div>
<div class="content">
<p>CONTENT</p>
</div>
<div class="bottom">
<div class="clear">
<div class="left">
*
</div>
<div class="right">
*
</div>
</div>
<div class="clear">
<div class="left">
*
</div>
<div class="right">
*
</div>
</div>
<div class="clear">
<div class="left">
****
</div>
<div class="right">
****
</div>
</div>
</div>
and CSS:
.shell { width: 200px;}
.left{ float:left; }
.right{float:right; }
.clear { clear: both; line-height: 10px; }
.content { line-height: 10px; text-align: center; }
Here is a modified version of the above answer, this version has relative positioned parent and absolute positioned child so we can add the on hover effect.
http://jsfiddle.net/3jo5btxd/
HTML:
<div id="div1"><div id="div2"><img src="http://placekitten.com/g/82/82"></div></div>
CSS:
#div1 {
position: relative;
height: 100px;
width: 100px;
background-color: white;
border: 1px solid transparent;
}
#div2 {
position: absolute;
top: -2px;
left: -2px;
height: 84px;
width: 84px;
background-color: #FFF;
border-radius: 15px;
padding: 10px;
}
#div1:hover {
border: 1px solid red;
}
I liked #Tims approach, but it forced me to set a background color to the box, which I did not want, since I it to put the focus on a background image object.
In my case I only needed 2 edges also, which makes it possible to structure it a little different.
I therefore structured it a little different, that makes it more flexible and still works in every browser.
The solution does not work if you need 4 corners, but just wanted to leave it here for future searchers.
:root {
--border-width: 5px;
--corner-size: 20px;
--border-color: red;
}
.box-corners {
position:relative;
}
.box-corners::before,
.box-corners::after {
content: "";
position: absolute;
width:var(--corner-size);
height:var(--corner-size);
border:var(--border-width) solid var(--border-color);
}
.box-corners::before {
left: 0;
top: 0;
border-bottom:none;
border-right:none;
}
.box-corners::after {
bottom: 0;
right: 0;
border-left:none;
border-top:none;
}
/* ############## THIS IS JUST OPTIONAL FOR THE HOVER EFFECT ############# */
.box-corners {
transition:background-color 0.3s ease-in-out;
}
.box-corners:hover {
background:rgba(0, 0, 0, 0.5)!important;
}
.box-corners::before,
.box-corners::after {
box-sizing:border-box;
transition:width 0.3s ease-in-out, height 0.3s ease-in-out;
}
.box-corners:hover::before,
.box-corners:hover::after {
width:100%;
height:100%;
}
<div class="box-corners" style="width:300px;height:300px;background:#f7f7f7;" />
Hover effect
You only need the first part of the css code to make the edges work.
The second part just allows to easily add a nice hover effect, that you could also just remove, if you don't need it.
Without CSS Variables and Sass
If you don't want to use css variables, you can just replace the variables with hardcoded values.
If you want to make a sass mixin out of it, just wrap it in a #mixin call and replace the vars with sass variables.
.border_coners {
background:
linear-gradient(to right, #e5e5e5 1px, transparent 1px) 0 0,
linear-gradient(to right, #e5e5e5 1px, transparent 1px) 0 100%,
linear-gradient(to left, #e5e5e5 1px, transparent 1px) 100% 0,
linear-gradient(to left, #e5e5e5 1px, transparent 1px) 100% 100%,
linear-gradient(to bottom, #e5e5e5 1px, transparent 1px) 0 0,
linear-gradient(to bottom, #e5e5e5 1px, transparent 1px) 100% 0,
linear-gradient(to top, #e5e5e5 1px, transparent 1px) 0 100%,
linear-gradient(to top, #e5e5e5 1px, transparent 1px) 100% 100%;
background-repeat: no-repeat;
background-size: 50px 50px;
}
I adapted the border radius approach, but I didn't want to use absolute positioning or have to know the size of the content.
Fortunately setting a negative margin in all directions provides everything we need:
.corner-borders {
border: 1px solid #ccc;
}
.corner-borders-reveal {
border-radius: 20%; /* or any other size */
border: 1px solid white;
margin: -1px;
padding: 4px;
}

How to create a div with an irregular shape?

Is it possible to create a div with an irregular shape with CSS? I already searched but I can't find a good example. The style is something like this:
/
/ \
/ \
/ \
/___________________________\
There should be a line on the top that connects it. Basically it has different height on the left and right side.
THE SVG WAY
Since the shape you request is not possible with only CSS, I suggest you use SVG to draw the shape.
The following piece of code will create the below shape:
<svg height="150" width="150">
<polygon points="20,10 100,30 120,100 0,100" style="fill:red;" />
</svg>
SVG is a powerful tool to make shapes otherwise impossible without using images. Read up on it here.
HTML & CSS Answer
This can be done by using perspective and transform. You create two divs: one that will get the perspective and one that will be transformed. Just know that anything in the .test-div will also be transformed, so if you put text in there, it will also get transformed.
.wrapper {
width: 100px;
height: 100px;
margin-left: 100px;
perspective: 150px;
}
.test {
height: 100px;
width: 100px;
background: red;
transform: rotateX(45deg);
}
<div class="wrapper">
<div class="test"></div>
</div>
Result
JSFIDDLE
This can also be done using CSS clip-path
div {
width: 200px;
height: 150px;
background: red;
-webkit-clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
}
<div></div>
You can then just change the background element if you need an image.
div {
width: 200px;
height: 150px;
background: url(https://lorempixel.com/200/150/);
-webkit-clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
clip-path: polygon(20% 10%, 85% 30%, 100% 100%, 0% 100%);
}
<div></div>
In their current state, clip-paths aren't as widely supported as inline or imported SVG but is a much cleaner, and in some cases, easier variant to use.
Browser Support
You can try using overflow hidden and transforms, though the best approach will be svg.
HTML
<div class="out">
<div class="in"></div>
</div>
CSS
body { background:url(http://www.placecage.com/g/640/480) }
.out {
height: 100px;
width: 150px;
transform-origin: 0% 100%;
transform: skew(-10deg);
overflow: hidden;
}
.in {
height: 110px;
width: 148px;
position: relative;
left: -43px;
top: -7px;
transform-origin: 0% 0%;
transform: skew(30deg) rotate(10deg);
background: rgba(9,40,0,0.8);
transition: 0.5s ease;
}
.in:hover {
background: rgba(50,0,70,0.7);
transition: 0.5s ease;
}
FIDDLE : https://jsfiddle.net/xb1jxd7g/
Following it for diamond and make a way around to rotate it and you'll get your shape :
#diamond-shield {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom: 20px solid red;
position: relative;
top: -50px;
}
#diamond-shield:after {
content: '';
position: absolute;
left: -50px; top: 20px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top: 70px solid red;
}

Two gradients with two distinct sections with just one div element

I was wondering if it is possible to create a background effect like in the image below using just one div.
I know how to achieve it with two divs, but my situation would make it really easy if it could be done in one div (maybe using :after ???). The code for the gradients is:
.bg-green {
background-image: linear-gradient(-180deg, #95D428 0%, #20560B 100%);
}
.bg-red {
background-image: linear-gradient(-180deg, #F5515F 0%, #8E0A1E 100%;
}
Thanks :)
Yes, this is possible using a single div with a :pseudo-element.
What you could do is add the second linear-gradient to its :after :pseudo-element. Notice the use of rgba(r, b, g, a) instead of hex colors. This way you could control the opacity of the second linear-gradient by changing its alpha value.
body, html {
height: 100%;
margin: 0;
}
div {
width: 100%;
height: 100%;
position: relative;
background: linear-gradient(110deg, #5EDC29 45%, #FF0058 45%, #FF0058 100%);
z-index: -1;
}
div:after {
content: '';
position: absolute;
width: 100%;
height: 100%;
background-image: linear-gradient(-180deg, transparent 0%, rgba(0,0,0,0.6) 100%);
}
<div></div>
If you want the exact same gradient colors that you've posted in your question, you'll need clipPath.
body {
background: #222222;
margin: 0;
}
.bg {
width: 500px;
height: 300px;
background: linear-gradient(-180deg, #F5515F 0%, #8E0A1E 100%);
}
.bg-2 {
position: absolute;
width: 500px;
height: 300px;
top: 0;
z-index: -1;
background-image: linear-gradient(-180deg, #95D428 0%, #20560B 100%);
}
<svg width="500" height="300">
<defs>
<clipPath id="shape">
<path d="M300,0 L501,0 L501,301 L175,301z" />
</clipPath>
</defs>
<foreignObject clip-path="url(#shape)" width="500" height="300">
<div class="bg"></div>
</foreignObject>
</svg>
<div class="bg-2"></div>
You can get this effect, but you will need to set overflow hidden on the div and to set the background in a after pseudo class
.test {
width: 400px;
height: 300px;
border: solid 1px black;
position: relative;
overflow: hidden;
}
.test:after {
content: "";
position: absolute;
width: 160%;
height: 160%;
top: -30%;
left: -30%;
background-image: linear-gradient(-210deg, #95D428 0%, #20560B 100%), linear-gradient(-210deg, #F5515F 0%, #8E0A1E 100%);
background-position: top left, top right;
background-size: 50% 100%;
background-repeat: no-repeat;
-webkit-transform: rotate(30deg);
}
<div class="test"></div>
The after is rotated to get the inclined separation. The dimensions need to be bigger so as not to show missing corners.
And then, you assign the 2 linear gradients as 2 separate background-images,inclined an additional 30deg to compensate for the base inclination

Implement a rectangle shape with a transparent triangular cut at bottom

I want to create a non-rectangular image with CSS3, I think implement something like below image
It is a square with a transparent triangle gap in bottom of it, I know I can implement it with some trick, as example with png image but I want create this with HTML element not with image,
any body know how can I do that? Is that implementable with HTML and CSS?
<----------------------------------------------- clip-path solution ------------------------------------------------->
You could use clip-path to do this:
dabblet
.rect {
position: absolute;
width: 165px;
height: 100px;
background-color: black;
-webkit-clip-path: polygon(0 0, 0 100%, 40% 100%, 50% 75%, 60% 100%, 100% 100%, 100% 0%);
}
body {
background-color: lightblue;
}
Note: Firefox does not support this property.
Works fine on Chrome.
Check out the browser support for clip-path ----------> HERE.
<------------------------- <svg> solution - will support all browsers [except IE8] ------------------------->
Since, Firefox still supports clip-path: url(), you can create an inline svg element with a polygon element inside clipPath that defines the points. Give the clipPath element an id(#mask) and use it in CSS instead of polygon(0 0, 0 100%, 40% 100%, 50% 75%, 60% 100%, 100% 100%, 100% 0%);.
dabblet
HTML:
<div class="rect"></div>
<svg>
<defs>
<clipPath id="mask">
<polygon points="0,0 0,100 66,100 82.5,75 99,100 165,100 165,0 " />
</clipPath>
</defs>
</svg>
CSS:
.rect {
position: absolute;
width: 165px;
height: 100px;
background-color: black;
-webkit-clip-path: url(#mask);
clip-path: url(#mask);
}
body {
background-color: lightblue;
}
<---------------------------------------- <svg> solution without any CSS ---------------------------------------->
dabblet
HTML:
<svg>
<polygon points="0,0 0,100 66,100 82.5,75 99,100 165,100 165,0" style="fill:black" />
</svg>
Check out browsers that supports svg ----------> HERE
A simple approach
Use box-shadow on pseudoelement, and use overflow: hidden; on main element.
div {
height: 150px;
width: 200px;
position: relative;
overflow: hidden;
}
div:before{
position: absolute;
top: 100px;
left: 67px;
content: "";
height: 50px;
width: 50px;
background: transparent;
transform-origin:0% 100%;
transform: rotate(52deg) skewX(10deg);
-webkit-transform: rotate(52deg) skewX(10deg);
box-shadow: 0 0 0 200px black;
}
<div></div>
One way to produce this transparent cut at the bottom is to use a couple of skewed pseudo-elements and position them such that they leave a triangle shaped gap at the bottom. Below is a sample snippet demonstrating this approach.
body {
background: url("http://lorempixel.com/200/400");
}
.shape {
height: 200px;
width: 200px;
overflow: hidden;
position: relative;
}
.shape:before {
height: 100%;
width: 100%;
position: absolute;
content: '';
background: black;
left: 0px;
top: 0px;
-webkit-transform: skew(-30deg);
-moz-transform: skew(-30deg);
transform: skew(-30deg);
-webkit-transform-origin: 25% -25%;
-moz-transform-origin: 25% -25%;
transform-origin: 25% -25%;
}
.shape:after {
height: 100%;
width: 100%;
position: absolute;
content: '';
right: 0px;
top: 0px;
background: black;
-webkit-transform: skew(30deg);
-moz-transform: skew(30deg);
transform: skew(30deg);
-webkit-transform-origin: 25% -25%;
-moz-transform-origin: 25% -25%;
transform-origin: 25% -25%;
}
<div class="shape"></div>
Note: This below snippet is only to show that achieving a shape with transparent cut is possible by using overlapping gradient backgrounds. However, my advice would be to not use this approach as much as possible because gradients produce jagged corners a lot of the times.
You can use two overlapping linear-gradient backgrounds on a div to achieve this effect. The angles of the triangle can be modified by modifying the gradient's angles. This is tested and found to be working fine in Mozilla FireFox, Chrome, Safari and Opera.
body {
background: url("http://lorempixel.com/200/400");
}
.shape {
height: 200px;
width: 400px;
background: -webkit-linear-gradient(-10deg, black 50%, transparent 50%), -webkit-linear-gradient(10deg, transparent 50%, black 50%);
background: -moz-linear-gradient(-10deg, black 50%, transparent 50%), -moz-linear-gradient(10deg, transparent 50%, black 50%);
background: linear-gradient(100deg, black 50%, transparent 50%), linear-gradient(-100deg, black 50%, transparent 50%);
}
<div class="shape"></div>
One potential drawback of this approach is that the edges aren't really sharp in Chrome (atleast in older versions of Chrome) whereas it is sharp in the others.

How to strike through obliquely with css

I need something like this:
How can achieve this with css? I know that one way is use background image, but can I achieve this only with css without any image?
There is a hacky way to do this, using the :before pseudo element. You give the :before a border, then rotate it with a CSS transform. Doing it this way adds no extra elements to the DOM, and adding/removing the strikethrough is a simple as adding/removing the class.
Here's a demo
Caveats
This will only work down to IE8. IE7 does not support :before, however will degrade gracefully in browsers that do support :before but don't support CSS transforms.
The angle of rotation is fixed. If the text is longer, the line will not touch the corners of the text. Be mindful of this.
CSS
.strikethrough {
position: relative;
}
.strikethrough:before {
position: absolute;
content: "";
left: 0;
top: 50%;
right: 0;
border-top: 1px solid;
border-color: inherit;
-webkit-transform:rotate(-5deg);
-moz-transform:rotate(-5deg);
-ms-transform:rotate(-5deg);
-o-transform:rotate(-5deg);
transform:rotate(-5deg);
}
HTML
<span class="strikethrough">Deleted text</span>
You can use background linear-gradient with currentColor to avoid hardcoding font color:
.strikediag {
background: linear-gradient(to left top, transparent 47.75%, currentColor 49.5%, currentColor 50.5%, transparent 52.25%);
}
.withpadding {
padding: 0 0.15em;
}
The value is <span class="strikediag">2x</span> 3x<br>
The number is <span class="strikediag">1234567890</span>.
<p>
The value is <span class="strikediag withpadding">2x</span>3x<br>
The number is <span class="strikediag withpadding">1234567890</span>.
If you don't need the element to be fully inline, you can use a pseudo element to place the line on top of the element. This way the angle can be adjusted by changing the pseudo element's size:
.strikediag {
display: inline-block;
position: relative;
}
.strikediag::before {
content: '';
position: absolute;
left: -0.1em;
right: -0.1em;
top: 0.38em;
bottom: 0.38em;
background: linear-gradient(to left top, transparent 45.5%, currentColor 47.5%, currentColor 52.5%, transparent 54.5%);
pointer-events: none;
}
The value is <span class="strikediag">2x</span> 3x<br>
The number is <span class="strikediag">1234567890</span>.
del {
position:relative;
text-decoration:none;
}
del::after {
content:"";
position:absolute;
top:50%; left:0; width:100%; height:1px;
background:black;
transform:rotate(-7deg);
}
Enhancing Bojangles answer from above:
.strike-diagonal-price {
position: relative;
background-color: black;
color: white;
}
.strike-diagonal-price:before {
position: absolute;
content: "";
left: 0;
top: 45%;
right: 0;
border-top: 2px solid;
border-color: red;
-webkit-transform: rotate(-25deg);
-moz-transform: rotate(-25deg);
-ms-transform: rotate(-25deg);
-o-transform: rotate(-25deg);
transform: rotate(-25deg);
}
Now I get the affect I needed:
I think you could probably apply a rotation effect to a horizontal rule. Something like:
<html>
<body>
<hr />
123456
</body>
</html>
With the CSS:
hr
{
width: 50px;
position: absolute;
background-color: #000000;
color: #000000;
border-color: #000000;
transform:rotate(-7deg);
-ms-transform:rotate(-7deg);
-moz-transform:rotate(-7deg);
-webkit-transform:rotate(-7deg);
-o-transform:rotate(-7deg);
}
Fiddle
Your mileage may vary depending on browser and version though, so I'm not sure if I'd resort to this. You might have to pull off some funky VML code to support older versions of IE, for example.
CSS3 gradient
background-image: linear-gradient(left bottom, rgb(234,20,136) 0%, rgb(255,46,164) 50%, rgb(255,74,197) 0%);
background-image: -o-linear-gradient(left bottom, rgb(234,20,136) 0%, rgb(255,46,164) 50%, rgb(255,74,197) 0%);
background-image: -moz-linear-gradient(left bottom, rgb(234,20,136) 0%, rgb(255,46,164) 50%, rgb(255,74,197) 0%);
background-image: -webkit-linear-gradient(left bottom, rgb(234,20,136) 0%, rgb(255,46,164) 50%, rgb(255,74,197) 0%);
background-image: -ms-linear-gradient(left bottom, rgb(234,20,136) 0%, rgb(255,46,164) 50%, rgb(255,74,197) 0%);
background-image: -webkit-gradient( linear, left bottom,right top,color-stop(0, rgb(234,20,136)), color-stop(0.5, rgb(255,46,164)), color-stop(0, rgb(255,74,197)) );
My example won't fill your needs perfectly but, for more info and funny tweaks, see http://gradients.glrzad.com/.
What you have to do is create a background-gradient of white-black-white and position your opacity at something like 48% 50% 52%.
This is an old question but as an alternative you can use CSS3 Linear Gradients for example (http://codepen.io/yusuf-azer/pen/ojJLoG).
For extensive explaining and a LESS Solution check
http://www.yusufazer.com/tutorials-how-to/how-to-make-a-diagonal-line-through-with-css3/
span.price--line-through {
background-color: transparent;
background-image: -webkit-gradient(linear, 19.1% -7.9%, 81% 107.9%, color-stop(0, #fff), color-stop(.475, #fff), color-stop(.5, #000), color-stop(.515, #fff), color-stop(1, #fff));
background-image: -webkit-repeating-linear-gradient(287deg, #fff 0%, #fff 47.5%, #000 50%, #fff 51.5%, #fff 100%);
background-image: repeating-linear-gradient(163deg, #fff 0%, #fff 47.5%, #000 50%, #fff 51.5%, #fff 100%);
background-image: -ms-repeating-linear-gradient(287deg, #fff 0%, #fff 47.5%, #000 50%, #fff 51.5%, #fff 100%);
}
I don't think there is a sustainable css solution to this.
My pure CSS solution would be to place another element of text behind your first element of text that is identical in number of characters (characters being ' '), a text-decleration of line-through, and a transform of rotate.
Something like:
<html>
<head>
<style>
.strike{
text-decoration: line-through;
-webkit-transform: rotate(344deg);
-moz-transform: rotate(344deg);
-o-transform: rotate(344deg);}
</style>
</head>
<body>
<p>Text to display</p>
<p class='strike'></p>
</body>
</html>
Text Rotation example
I am looking forward to seeing better answers from other users.
Here is my solution using clip-path, which is responsive also
p{
position : relative
}
span{
position: absolute;
width: 100%;
height: 100%;
color : black;
clip-path: polygon(100% 0 , 100% 12% ,0% 100% , 0% 88%);
}
<p><span/>$100</p>
I did it this way using an SVG in the HTM with a CSS class:
HTML:
<ul>
<li>Regular Price: <div class="zIndex-10a">$4.50</div><div class="zIndex-10b"><svg height="16" width="5"><line x1="0" y1="20" x2="40" y2="0" class="Strike-01a"></svg></div></li>
</ul>
CSS:
/* -- CONTAINS TEXT TO STRIKE ---- */ .zIndex-10a { display: inline-block; position: relative; left: 0px; z-index: 10; }
/* -- CONTAINS SVG LINE IN HTML -- */ .zIndex-10b { display: inline-block; position: relative; right: 40px; z-index: 11; }
/* -- SVG STROKE PROPERTIES ------ */ .Strike-01a { stroke: rgb(255,0,0); stroke-width:2; }
There might be simpler easier ways by now. I just cooked this up in a pinch for my product detail special offer page. Hope it helps someone.
Try
.mydiv {
background-color: #990000;
color: #FFFF00;
font-size: 2em;
padding-top: 10px;
padding-bottom: 10px;
border-radius: 15px;
max-width: 300px;
width: 100%;
}
.strikethrough-100p, .strikethrough-50p{
position: relative;
text-align: center;
}
.strikethrough-100p:before {
position: absolute;
content: "";
left: 0;
top: 50%;
right: 0;
border-top: 3px solid;
border-color: inherit;
-webkit-transform:rotate(-5deg);
-moz-transform:rotate(-5deg);
-ms-transform:rotate(-5deg);
-o-transform:rotate(-5deg);
transform:rotate(-5deg);
}
.strikethrough-50p:before {
position: absolute;
content: "";
width:50%;
left: 25%;
top: 50%;
right: 0;
border-top: 3px solid;
border-color: inherit;
-webkit-transform:rotate(-5deg);
-moz-transform:rotate(-5deg);
-ms-transform:rotate(-5deg);
-o-transform:rotate(-5deg);
transform:rotate(-5deg);
}
<div class="mydiv">
<div class="strikethrough-100p">123456</div>
</div>
<br>
<div class="mydiv">
<div class="strikethrough-50p">123456</div>
</div>
And here's a fancy version:
background:none repeat scroll 0 0 rgba(255, 0, 0, 0.5);
-moz-border-radius:20px 0;
-webkit-border-radius:20px 0;
border-radius:20px 0;
content: "";
height:5px; left:-5%;
position:absolute;
top:30%;
-moz-transform:rotate(-7deg);
-webkit-transform:rotate(-7deg);
transform:rotate(-7deg);
transform-origin:50% 50% 0;
width:110%;