Creating a skewed triangle shape - html

Is it possible to create the shape produced by this Fiddle. But then with no JavaScript but CSS3 (with <div>) ?
Basically this:
for(var i = 0; i < coords.length; i += 1) {
if(coords[(i + 1)] != undefined) {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[(i + 1)].x, coords[(i + 1)].y);
ctx.stroke();
} else {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[0].x, coords[0].y);
ctx.stroke();
}
}
So you have points that needs to connect to each other?

Use svg, if you don't want to use canvas.
<svg width="100" height="100">
<path d="M0 0 l100 10 l-40 90z" fill="none" stroke="black" stroke-width="2" />
</svg>
Path command for 8,8,10,10,30,30,49,10 would be M8 8 L10 10 L30 40 L49 10z.
<svg width="49" height="40" viewBox="0 0 50 41">
<path d="M8 8 L10 10 L30 40 L49 10z" fill="none" stroke="black" stroke-width="2" />
</svg>
To apply a click event to the shape, you could use pointer-events: all on #test.
#test {
pointer-events: all;
}
<svg width="49" height="40" viewBox="0 0 50 41">
<path id="test" d="M8 8 L10 10 L30 40 L49 10z" fill="none" onclick="alert('Works')" stroke="black" stroke-width="2" />
</svg>

Note: Posting this answer just because you asked with CSS3, but the complexity and possible calculation overhead involved in this approach is proof enough why CSS shouldn't be used for this. Please do not use this approach.
A bit of explanation on how this was achieved:
A div is created with top and right border (1px black) and the other two borders are set to none.
This div is then skewed a bit to make it appear as though the edge on the right side is a bit slanted.
Inside the shape, a pseudo-element with only a right border is created and it is also skewed to produce the diagonal line from the right-bottom to the left-top. Transform origin is set as right-bottom to avoid positioning overhead.
An anchor tag is added within the parent div and the overflow is set to hidden so that only the portion within the shape is clickable.
The user select on the anchor tag are disabled to prevent a double click from selecting a blank space within the div.
Finally the whole container div is rotated a bit to make it look as though the triangle is not parallel to x-axis.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 50px;
width: 45px;
border: 1px solid black;
border-left: none;
border-bottom: none;
-webkit-transform: skew(-10deg) rotate(5deg);
-moz-transform: skew(-10deg) rotate(5deg);
transform: skew(-10deg) rotate(5deg);
overflow: hidden;
}
a {
display: block;
content: '';
margin-left: 0px;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
height: 100%;
width: 100%;
}
div:after {
position: absolute;
top: 0px;
left: 0px;
content: '';
height: 50px;
width: 45px;
-webkit-transform: skew(42deg);
-webkit-transform-origin: left bottom;
-moz-transform: skew(42deg);
-moz-transform-origin: left bottom;
transform: skew(42deg);
transform-origin: left bottom;
border-right: 1px solid black;
}
<div>
</div>
Another option to create a skewed triangle shape would be to use clip-path like in below snippet. The shape is created by applying the same clip-path on the main container element and a pseudo-element which is smaller than the container.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 150px;
width: 150px;
background: black;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
div:after{
position: absolute;
content: '';
height: calc(100% - 5px);
width: calc(100% - 5px);
top: 2px;
left: 3px;
background: white;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 250px;
}
<div id="clickme"></div>

You can do it by embeding SVG as CSS. Quote from:
http://css-tricks.com/using-svg/
"Another way to use SVG's is to convert them into Data URI's. Data URI's might not save you actual file size, but can be more efficient because the data is right there. It doesn't require an additional HTTPRequest.
Mobilefish.com has an online conversion tool for that (http://www.mobilefish.com/services/base64/base64.php). Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back.
...
You can use that anywhere we've talked about so far (except inline because that just doesn't make sense) Just put the gibberish where it says [data] in these examples.
As CSS
.logo {
background: url(data:image/svg+xml;base64,[data]);
}
"

Related

How to implement a repeating SVG at the top and bottom of a div? [duplicate]

I've been working on a header with a zigzag border. One way to do this is to use images to make the zigzag effect.
(1) Is there any way to create a practical cross-browser zigzag border in CSS without the use of images?
I am also trying to put a textured background on this header that extends to the zigzags. However, the vertical size of the header may change and I am unable to implement the header as a single image.
If I try to add a texture to both the zigzag edges and the header element, chances are, the texture will be off sync.
(2) Any ideas on implementing a textured background that extends onto the zigzags without being off sync?
My [old] code (along with a texture) is here on jsFiddle.
body {
padding: 20px;
}
header {
width: 240px;
background-color: #BCED91;
}
header:after {
content: " ";
display: block;
position: relative;
width: 240px;
bottom: -15px;
height: 15px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAPCAYAAACWV43jAAAAw0lEQVRIx83RsQ3CMBCF4T83AZKLVOmyBa1HSIlXwKySGaDOBClZAToWQIpETQONyxAS+2J4pe9knd5X9EP7QicPYAsUwBnYaHwqSsd1QGmNv1rjL0AZ3pJTKDTorPGnsUE/tDvg+KsG70D96TiAMKvDbtYDO6Cyxt++LYadKpY8hthNtTaVGHLRJJ3R5mJy0SbVJp9D7FJaSyWXNUk1yGVt0lTyMWK3ZmtLySUnaQy55CZdSi7AHmis8U/+JOGWBji8AaYPVy6VELZvAAAAAElFTkSuQmCC) repeat-x;
}
img {
margin-top: 50px;
}
<header>
<br />
<br />
<br />
<br />
</header>
<img src="http://i.imgur.com/qKsVr.png" />
Edit #1:
Thank you Ana for the code. I took it and improved upon it.
http://dabblet.com/gist/3401493
I don't think that a consistent background will be possible.
If you are going to use border-image, then it's not a cross-browser solution because IE doesn't support it.
Also, even though every current browser version except IE9 supports both CSS gradients (which would allow you to get a zig-zag pattern) and border-image, last time I checked (which was quite a few months ago, so better test this again), using gradients for border-image only worked in WebKit. Plus, I don't think that even in WebKit this works with more than one gradient (as you can only set one border image and one gradient is one image) and you need two gradients for the zig-zag pattern.
The code for the CSS zig-zag pattern is:
background: linear-gradient(#BCED91 49%, transparent 49%),
linear-gradient(-45deg, white 33%, transparent 33%) 0 50%,
white linear-gradient(45deg, white 33%, #BCED91 33%) 0 50%;
background-repeat: repeat-x;
background-size: 1px 100%, 40px 40px, 40px 40px;
If you want a texture below this that is in sync with this one, then you have to make sure it repeats at the same intervals (40px, but you could also go for 20px).
Edit: regarding polyfills, you could try one of the ones listed here: CSS3 PIE or cssSandpaper
(In modern browsers) you can use SVGs to create simple drawings, and use them as CSS background images embedded as data URI.
Here is what the SVGs look like:
body {
background: #888;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,4 4,0 8,4" fill="#CC0000" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,0 4,4 8,0" fill="#CC0000" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,0 4,4 8,0" fill="#FFFFFF" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,4 4,0 8,4" fill="#FFFFFF" />
</svg>
Example 1:
.zigzag-outside {
position: relative;
margin-top: 4px;
margin-bottom: 4px;
background-color: #CC0000;
/* example content */
padding: 1em;
font: bold medium sans-serif;
color: #FFFFFF;
}
.zigzag-outside:before {
content: "";
position: absolute;
top: -4px;
left: 0;
right: 0;
height: 4px;
/* red up pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C4%204%2C0%208%2C4%22%20fill%3D%22%23CC0000%22%2F%3E%3C%2Fsvg%3E");
}
.zigzag-outside:after {
content: "";
position: absolute;
bottom: -4px;
left: 0;
right: 0;
height: 4px;
/* red down pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C0%204%2C4%208%2C0%22%20fill%3D%22%23CC0000%22%2F%3E%3C%2Fsvg%3E");
}
<div class="zigzag-outside">Example 1</div>
Example 2:
.zigzag-inside {
position: relative;
/* example content */
width: 600px;
height: 100px;
background-image: url(http://i.stack.imgur.com/uOVfl.jpg);
}
.zigzag-inside:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
/* white down pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C0%204%2C4%208%2C0%22%20fill%3D%22%23FFFFFF%22%2F%3E%3C%2Fsvg%3E");
}
.zigzag-inside:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4px;
/* white up pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C4%204%2C0%208%2C4%22%20fill%3D%22%23FFFFFF%22%2F%3E%3C%2Fsvg%3E");
}
<div class="zigzag-inside"></div>
Improved minimal CSS:
div {
background: #1ba1e2;
position: relative;
}
div:after {
content: "";
display: block;
position: absolute;
width: 100%;
height: 30px;
background: linear-gradient(-45deg, transparent 75%, #1ba1e2 0) 0 50%,
linear-gradient(45deg, transparent 75%, #1ba1e2 0) 0 50%;
background-size: 30px 30px;
}
/* Styles just for demo */
h1 {
color: #fff;
text-align: center;
margin: 0;
padding: 0.5em;
}
<div>
<h1>Zig Zag Borders</h1>
</div>
If you want to remove duplicate values you can use CSS variables AKA Custom properties. They are working everywhere except IE.
:root {
--background-color: #1ba1e2;
--zigzag-item-size: 30px;
}
div {
background: var(--background-color);
position: relative;
}
div:after {
content: "";
display: block;
position: absolute;
width: 100%;
height: var(--zigzag-item-size);
background: linear-gradient(-45deg, transparent 75%, var(--background-color) 0) 0 50%,
linear-gradient(45deg, transparent 75%, var(--background-color) 0) 0 50%;
background-size: var(--zigzag-item-size) var(--zigzag-item-size);
}
/* Styles just for demo */
h1 {
color: #fff;
text-align: center;
margin: 0;
padding: 0.5em;
}
<div>
<h1>Zig Zag Borders</h1>
</div>
Small note:
I use zero 0 in gradient color-stops to avoid duplicating previous values because according to the CSS3 images specs color-stop position can't be less than previous one.
If a color-stop has a position that is less than the specified position of any color-stop before it in the list, set its position to be equal to the largest specified position of any color-stop before it.
Now using mask and one gradient you can do it. Check this online generator to get the code: https://css-generators.com/custom-borders/. You can find all the directions and combination of Zig-Zag
body {
padding: 20px;
}
header {
min-height: 200px;
background-color: #BCED91;
}
img {
margin-top: 50px;
}
.zig-zag {
--mask: conic-gradient(from -45deg at bottom,#0000,#000 1deg 90deg,#0000 91deg) 50% / 60px 100%;
-webkit-mask: var(--mask);
mask: var(--mask);
}
<header class="zig-zag">
</header>
<img src="http://i.imgur.com/qKsVr.png" class="zig-zag">

Elements hidden by clip-path still add to page length

I'm attempting an HTML page that has a diagonal border down the right-hand side. Well, in fact it has a semi-transparent border next to a solid border (to echo some design elements on other pages). The way I've created this line is by having two slightly rotated rectangles, one in the :before and one in the :after pseudo elements.
#header_block_unlimited:before {
content: '';
position: absolute;
width: 50%;
height: 130%;
right: -38.5%;
top: -10%;
bottom: -10%;
background-color: rgb(255, 255, 255); /* fallback */
background-color: rgba(255, 255, 255, 0.4);
-webkit-transition: all 1s;
-moz-transition: all 1s;
transition: all 1s;
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
transform: rotate(5deg);
}
#header_block_unlimited:after {
content: '';
position: absolute;
width: 50%;
height: 130%;
right: -40%;
top: -10%;
bottom: -10%;
background-color: #F95E62;
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
transform: rotate(5deg);
}
I suppose I could use an SVG shape, but I'm thinking this will take too long to fine-tune, especially since the page length needs to be dynamic (should be able to range between 400 pixels and about 1500 pixels).
I have attempted to use overflow-y:hidden but this produces a scroll bar on the x-axis, partly because the design also needs to use full-browser-width bars (see https://css-tricks.com/full-browser-width-bars/)
Clip-path to the rescue! Well, unfortunately not quite. Clip-path crops off the bits at the bottom of the rectangle I don't need, but unfortunately still counts those bits to the length of the page, meaning there is a gap beneath my footer.
Here's the clip-path code that's assigned to the parent container...
clip-path: inset( -100vw -100vw 0 -100vw);
Here's a codepen of the problem.
Any help with this would be much appreciated. An ideal solution would be some way of cropping the excess of the rotated rectangles so that it doesn't add to the page length. Alternatively, some other way of achieving the diagonal RHS border.
Instead of clip-path and complex transformation I would a simple linear-gradient to create this:
body {
margin:0;
height:100vh;
background:linear-gradient(100deg, transparent 70%,#F95E62 70.5%);
}
While I liked the simplicity of Temani Afif's answer, I was unable to get it working without the diagonal line either being blurry or pixelated.
After some fiddling, I was able to solve the problem using an SVG file, created from the original Adobe Illustrator artwork.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
height="1700px" width="300px" viewBox="0 14 300 1715">
/* Note that the SVG needs to have an implicit height and width
to avoid problems in Firefox */
<defs>
<style>
.cls-1{opacity:0.36;}
.cls-2{fill:#fff;}
.cls-3{fill:#f95e62;}
</style>
</defs>
<title>Asset 3</title>
<g class="cls-1">
<polyline class="cls-2" points="167.05 13.28 8.5 1721 334 1721 334 1721 334 13"/>
</g>
<polyline class="cls-3" points="334 1721 334 13 197 13 40.25 1720.99"/>
</svg>
I then added it in a div just inside my main container div.
<div id="header_triangle">
<img src="[path to the svg]" />
</div>
For which the styling is as follows...
#header_triangle {
position: absolute;
top: 0;
bottom: 0;
right: 0;
z-index: 100; /* needs to sit on top */
}
#header_triangle img {
height: 102%;
float: right; /* to Fix an issue in FF */
}
Here's the working CodePen.

Using CSS3 turn triangle into square with animation on hover

I am trying to develop a CSS box hover effect using HTML5 & CSS3 but I cannot get this to work. I would like to make an effect like seen below:
when the user is not hovering
when user is hovering
i.e. how can I make a blue triangle and turn it into a blue square when the user hovers over it using HTML5 and CSS3? I need this only using HTML5 & CSS3 and not using canvas.
This element work with canvas perfectly like as below
var ctx = document.getElementById("c").getContext("2d");
ctx.fillStyle = "#0000ff";
function normal() {
ctx.clearRect(0,0,256,256);
ctx.beginPath();
ctx.moveTo(256,256);
ctx.lineTo(256,0);
ctx.lineTo(0,0);
ctx.closePath();
ctx.fill(); bars()
ctx.fillStyle="#0000ff"; for (i=0;i
But I need only using HTML5 & CSS3 scripting languages
Using SVG: (the entire effect that you are looking for)
I know you've asked for HTML(5) + CSS(3) but you could also use a SVG path element to produce this effect like in the below snippet. (Note: This uses SVG animations and its browser support can be different compared to CSS animations.)
svg {
height: 150px;
width: 150px;
stroke: black;
}
#blue {
stroke: blue;
stroke-width: 10;
}
svg polygon {
fill: blue;
}
#white {
stroke: white;
stroke-width: 10;
}
#icon {
fill: transparent;
}
<svg viewBox='0 0 100 100'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 1,0 1,1 0,0z'>
<animate attributeType="XML" attributeName="d" from="M0,0 1,0 1,1 0,0z" to="M0,0 1,0 1,1 0,1z" dur="1s" begin="icon.mouseover" fill="freeze" />
<animate attributeType="XML" attributeName="d" from="M0,0 1,0 1,1 0,1z" to="M0,0 1,0 1,1 0,0z" dur="1s" begin="icon.mouseout" fill="freeze" />
</path>
</clipPath>
<g id='lines'>
<line x1='20' y1='30' x2='80' y2='30' />
<line x1='20' y1='50' x2='80' y2='50' />
<line x1='20' y1='70' x2='80' y2='70' />
</g>
</defs>
<use xlink:href='#lines' id='blue' />
<g clip-path='url(#clipper)'>
<polygon points='0,0 0,100 100,100 100,0' />
<use xlink:href='#lines' id='white' />
</g>
<g>
<polygon points='0,0 0,100 100,100 100,0' id='icon' />
</g>
</svg>
The below are answers to the question - how to turn triangle into square with animation.
Using Borders:
You could do it using border like in the below snippet. Initially only the right and top borders have the blue color but on hover we set the color to all border sides. This method is pretty simple and will work in all browsers (including IE8) but you cannot add content directly to this div (as doing so will affect the triangle shape) and so you'd have to place content on top of the shape using positioning or set the shape using a pseudo-element.
.shape{
height: 0px;
width: 0px;
border: 50px solid transparent;
border-color: blue blue transparent transparent;
transition: all 1s;
}
.shape:hover{
border-color: blue;
}
<div class='shape'></div>
Using Transforms:
You could add rotate transform on a pseudo-element, set overflow: hidden on parent to produce the triangle and then reverse/nullify the transform on hover.
.shape {
position: relative;
height: 100px;
width: 100px;
overflow: hidden;
}
.shape:after {
position: absolute;
content: '';
height: calc(100% * 1.414); /* using Pythogras theorem */
width: calc(100% * 1.414); /* using Pythogras theorem */
transform: rotate(-45deg);
transform-origin: left top;
background: blue;
transition: all 1s;
}
.shape:hover:after {
transform: rotate(0deg);
}
<div class='shape'></div>
You could also use a skewX transform instead of a rotate transform if you wish to avoid calculating the height and width like in the previous snippet.
.shape {
position: relative;
height: 100px;
width: 100px;
overflow: hidden;
}
.shape:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
transform: skewX(45deg);
transform-origin: left top;
background: blue;
transition: all 1s;
}
.shape:hover:after {
transform: skewX(0deg);
}
<div class='shape'></div>
Using Gradients:
You could use linear-gradients to create a triangle and then turn it into a square on hover by doubling the background-size.
.shape{
height: 100px;
width: 100px;
background: linear-gradient(to bottom left, blue 49.5%, transparent 50.5%);
background-position: 100% 0%;
background-size: 100% 100%;
transition: all 1s;
}
.shape:hover{
background-size: 200% 200%; /* just double the background size on hover */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='shape'></div>
In spite of the complete answer from Harry, couldn't resist to post an answer with another approach, suggested by the image in the OP.
Let's use blend modes, and see what can be achieved (but with more limited support)
.test {
width: 200px;
height: 200px;
background-color: white;
display: inline-block;
background-image: linear-gradient(blue, blue), linear-gradient(blue, blue), linear-gradient(blue, blue);
background-size: 100px 30px;
background-repeaT: no-repeat;
background-position: center 30px, center center, center 140px;
border: solid 1px black;
position: relative;
overflow: hidden;
}
.test:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: linear-gradient(45deg, yellow 50%, transparent 50%);
mix-blend-mode: difference;
transition: all 1s;
}
.one:after {
transform-origin: bottom right;
}
.one:hover:after {
transform: rotate(-45deg);
}
.two:hover:after {
opacity: 0;
}
.three:after {
background: none;
box-shadow: -1000px 1000px 0px 1000px yellow;
transform-origin: top left;
transform: rotate3d(1,1,0,87deg);
}
.three:hover:after {
transform: rotate3d(1,1,0,0deg);
}
<div class="test one"></div>
<div class="test two"></div>
<div class="test three"></div>
the third one is a little bit tricky, and not quite perfect. But you get the idea.

Infinity Symbol in CSS

I'm looking at creating a Infinity Symbol using CSS, SVG or Canvas.
If you don't know what an infinity symbol is, this is an example:
I have attempted at created the shape but have only managed to create one side of the shape. I would ultimately like to keep this to one element and as simple as possible.
.infinity {
width: 100px;
height: 100px;
border-radius: 50% 50% 0 50%;
border: 5px solid black;
transform: rotate(-45deg);
}
<div class="infinity"></div>
I have found this question:
Infinity symbol with HTML
But i'm looking at using this as an icon or image of some sort and therefore would like a bit more freedom with the shape.
CSS
By using pseudo-elements, you can create both sides of the shape and therefore get the output required.
This solution will be well supported across all browsers.
div {
position: relative;
width: 178px;
height: 100px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
border: 10px solid black;
border-radius: 50px 50px 0 50px;
transform: rotate(-45deg);
}
div:after {
left: auto;
right: 0;
border-radius: 50px 50px 50px 0;
transform: rotate(45deg);
}
<div></div>
This is an amended version from here: CSS-Tricks
If you want it more shapely, a bit of amending to the border radius rules really help give it some more shape.
div {
position: relative;
width: 178px;
height: 100px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
border: 10px solid black;
border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
transform: rotate(45deg);
}
div:after {
left: auto;
right: 0;
transform: rotate(-135deg);
}
<div></div>
SVG
SVG stands for Scalable Vector Graphic. The web browser views it as an image but you can add text and normal HTML elements within an SVG.
It is well supported across all browsers as viewable here: CanIUse
SVG | MDN
<svg height="150" viewbox="0 50 200 200">
<path fill="none" stroke="#333333" stroke-width="5" d="M100,100
C200,0 200,200 100,100
C0,0 0,200 100,100z" />
</svg>
Canvas
Canvas is similar to SVG but uses a raster (pixel based) instead of a vector to create the shape.
The browser support for Canvas is quite good.
var shape = document.getElementById('infinity').getContext('2d');
shape.lineWidth = 6;
shape.strokeStyle = "#333";
shape.beginPath();
shape.moveTo(100, 100);
shape.bezierCurveTo(200, 0, 200, 200, 100, 100);
shape.bezierCurveTo(0, 0, 0, 200, 100, 100);
shape.closePath();
shape.stroke();
<canvas id="infinity"></canvas>
HTML
As taken from the answer's in the near duplicate, this is an accumulation of all the HTML alternatives.
I've only added this for canonical and to show to users that the shape is possible with HTML entities.
p {
font-size: 2em;
}
<p>∞</p>
<p>∞</p>
<p>∞</p>
<p>∞</p>

CSS Zigzag Border with a Textured Background

I've been working on a header with a zigzag border. One way to do this is to use images to make the zigzag effect.
(1) Is there any way to create a practical cross-browser zigzag border in CSS without the use of images?
I am also trying to put a textured background on this header that extends to the zigzags. However, the vertical size of the header may change and I am unable to implement the header as a single image.
If I try to add a texture to both the zigzag edges and the header element, chances are, the texture will be off sync.
(2) Any ideas on implementing a textured background that extends onto the zigzags without being off sync?
My [old] code (along with a texture) is here on jsFiddle.
body {
padding: 20px;
}
header {
width: 240px;
background-color: #BCED91;
}
header:after {
content: " ";
display: block;
position: relative;
width: 240px;
bottom: -15px;
height: 15px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAPCAYAAACWV43jAAAAw0lEQVRIx83RsQ3CMBCF4T83AZKLVOmyBa1HSIlXwKySGaDOBClZAToWQIpETQONyxAS+2J4pe9knd5X9EP7QicPYAsUwBnYaHwqSsd1QGmNv1rjL0AZ3pJTKDTorPGnsUE/tDvg+KsG70D96TiAMKvDbtYDO6Cyxt++LYadKpY8hthNtTaVGHLRJJ3R5mJy0SbVJp9D7FJaSyWXNUk1yGVt0lTyMWK3ZmtLySUnaQy55CZdSi7AHmis8U/+JOGWBji8AaYPVy6VELZvAAAAAElFTkSuQmCC) repeat-x;
}
img {
margin-top: 50px;
}
<header>
<br />
<br />
<br />
<br />
</header>
<img src="http://i.imgur.com/qKsVr.png" />
Edit #1:
Thank you Ana for the code. I took it and improved upon it.
http://dabblet.com/gist/3401493
I don't think that a consistent background will be possible.
If you are going to use border-image, then it's not a cross-browser solution because IE doesn't support it.
Also, even though every current browser version except IE9 supports both CSS gradients (which would allow you to get a zig-zag pattern) and border-image, last time I checked (which was quite a few months ago, so better test this again), using gradients for border-image only worked in WebKit. Plus, I don't think that even in WebKit this works with more than one gradient (as you can only set one border image and one gradient is one image) and you need two gradients for the zig-zag pattern.
The code for the CSS zig-zag pattern is:
background: linear-gradient(#BCED91 49%, transparent 49%),
linear-gradient(-45deg, white 33%, transparent 33%) 0 50%,
white linear-gradient(45deg, white 33%, #BCED91 33%) 0 50%;
background-repeat: repeat-x;
background-size: 1px 100%, 40px 40px, 40px 40px;
If you want a texture below this that is in sync with this one, then you have to make sure it repeats at the same intervals (40px, but you could also go for 20px).
Edit: regarding polyfills, you could try one of the ones listed here: CSS3 PIE or cssSandpaper
(In modern browsers) you can use SVGs to create simple drawings, and use them as CSS background images embedded as data URI.
Here is what the SVGs look like:
body {
background: #888;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,4 4,0 8,4" fill="#CC0000" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,0 4,4 8,0" fill="#CC0000" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,0 4,4 8,0" fill="#FFFFFF" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
<polygon points="0,4 4,0 8,4" fill="#FFFFFF" />
</svg>
Example 1:
.zigzag-outside {
position: relative;
margin-top: 4px;
margin-bottom: 4px;
background-color: #CC0000;
/* example content */
padding: 1em;
font: bold medium sans-serif;
color: #FFFFFF;
}
.zigzag-outside:before {
content: "";
position: absolute;
top: -4px;
left: 0;
right: 0;
height: 4px;
/* red up pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C4%204%2C0%208%2C4%22%20fill%3D%22%23CC0000%22%2F%3E%3C%2Fsvg%3E");
}
.zigzag-outside:after {
content: "";
position: absolute;
bottom: -4px;
left: 0;
right: 0;
height: 4px;
/* red down pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C0%204%2C4%208%2C0%22%20fill%3D%22%23CC0000%22%2F%3E%3C%2Fsvg%3E");
}
<div class="zigzag-outside">Example 1</div>
Example 2:
.zigzag-inside {
position: relative;
/* example content */
width: 600px;
height: 100px;
background-image: url(http://i.stack.imgur.com/uOVfl.jpg);
}
.zigzag-inside:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
/* white down pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C0%204%2C4%208%2C0%22%20fill%3D%22%23FFFFFF%22%2F%3E%3C%2Fsvg%3E");
}
.zigzag-inside:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4px;
/* white up pointing triangle */
background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C4%204%2C0%208%2C4%22%20fill%3D%22%23FFFFFF%22%2F%3E%3C%2Fsvg%3E");
}
<div class="zigzag-inside"></div>
Improved minimal CSS:
div {
background: #1ba1e2;
position: relative;
}
div:after {
content: "";
display: block;
position: absolute;
width: 100%;
height: 30px;
background: linear-gradient(-45deg, transparent 75%, #1ba1e2 0) 0 50%,
linear-gradient(45deg, transparent 75%, #1ba1e2 0) 0 50%;
background-size: 30px 30px;
}
/* Styles just for demo */
h1 {
color: #fff;
text-align: center;
margin: 0;
padding: 0.5em;
}
<div>
<h1>Zig Zag Borders</h1>
</div>
If you want to remove duplicate values you can use CSS variables AKA Custom properties. They are working everywhere except IE.
:root {
--background-color: #1ba1e2;
--zigzag-item-size: 30px;
}
div {
background: var(--background-color);
position: relative;
}
div:after {
content: "";
display: block;
position: absolute;
width: 100%;
height: var(--zigzag-item-size);
background: linear-gradient(-45deg, transparent 75%, var(--background-color) 0) 0 50%,
linear-gradient(45deg, transparent 75%, var(--background-color) 0) 0 50%;
background-size: var(--zigzag-item-size) var(--zigzag-item-size);
}
/* Styles just for demo */
h1 {
color: #fff;
text-align: center;
margin: 0;
padding: 0.5em;
}
<div>
<h1>Zig Zag Borders</h1>
</div>
Small note:
I use zero 0 in gradient color-stops to avoid duplicating previous values because according to the CSS3 images specs color-stop position can't be less than previous one.
If a color-stop has a position that is less than the specified position of any color-stop before it in the list, set its position to be equal to the largest specified position of any color-stop before it.
Now using mask and one gradient you can do it. Check this online generator to get the code: https://css-generators.com/custom-borders/. You can find all the directions and combination of Zig-Zag
body {
padding: 20px;
}
header {
min-height: 200px;
background-color: #BCED91;
}
img {
margin-top: 50px;
}
.zig-zag {
--mask: conic-gradient(from -45deg at bottom,#0000,#000 1deg 90deg,#0000 91deg) 50% / 60px 100%;
-webkit-mask: var(--mask);
mask: var(--mask);
}
<header class="zig-zag">
</header>
<img src="http://i.imgur.com/qKsVr.png" class="zig-zag">