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.
Related
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">
I just want to animate my image through curved path. Like this way. ( I'm using position absolute for positioning. ) Did some research and found that css transform can do the job. It can be easily done by straight line. But curved path?
I tried to combine with css transform-origin + transform:rotate but I didn't get exact that I want. Clearly I want to move around 80% to the left curved and need to come to original position. I tried so many times adjusting my code but still no luck.
Fiddle
P.S
What is transform-origin really do here? Is it necessary?
Can someone explain me about how transform:rotate works here?
Here is my code
.sun{
width: 5.7%;
position: absolute;
top: -5%;
left: 57%;
animation: circle 10s linear infinite;
transform-origin: 0px 700px;
animation-fill-mode: forwards;
animation-direction: alternate;
}
#keyframes circle {
from {
transform:rotate(-60deg);
}
to {
transform:rotate(40deg);
}
}
<div class="sun">
<img src="sun.png" alt="">
</div>
Maybe make parent element move by rotate and children (in my case pseudoelement, whatever) make position absolute to the parent. And just use animation. Look at my solution. Maybe you will have to create some wrapper and use overflow: hidden, because it is square which is rotating. You can watch square's behavior by adding background-color.
#keyframes move-sun {
from {
transform: rotate(0deg);
}
to {
transform: rotate(90deg);
}
}
.sun {
position: relative;
width: 400px;
height: 400px;
margin: 200px;
transform: rotate(90deg);
animation: move-sun 10s;
}
.sun::before {
content: "";
position: absolute;
top: -25px;
left: -25px;
width: 50px;
height: 50px;
background-color: #ff0;
border-radius: 50%;
}
<div class="sun">
</div>
I realize this is an old question, but I just wanted to add another option. You could use 2 separate animations, one for the x-motion and one for the y-motion:
body {
background: #8DBECC;
}
.container {
position: relative;
height: 100%;
width: 100%;
}
.sun {
position: absolute;
width: 30px;
height: 200px;
animation: x-motion 3s ease-in-out 0s infinite alternate;
}
.sun:before {
content: '';
width: 30px;
height: 30px;
position: absolute;
top: 100%;
background: #F18C3E;
animation: y-motion 3s ease-in-out 0s infinite alternate;
border-radius: 15px;
}
#keyframes x-motion {
0% {
left: 0;
}
100% {
left: calc(100% - 30px);
}
}
#keyframes y-motion {
0%, 100% {
top: 100%;
}
50% {
top: 0%;
}
}
<html>
<body>
<div class="container">
<div class="sun">
</div>
</div>
</body>
</html>
https://jsfiddle.net/561pbt0r/27/
It might not be easy with CSS, but you can easily do this with SVG animation.
I modified a sample from this tutorial for your case:
<svg width="500" height="350" viewBox="0 0 350 350">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10" d="M100,100Q250,-50,400,100"/>
<g id="sun" transform="translate(-100, -300)">
<circle cx="100" cy="300" r="25" fill="yellow"/>
</g>
<animateMotion
xlink:href="#sun"
dur="3s"
begin="0s"
fill="freeze"
repeatCount="indefinite"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
When you want to apply some transform operation to an element, that transformation has a reference point from where it will be applied. That is the origin point and by default it is at the center of every element (i.e.: transform-origin(50% 50%)).
With this statement you can modify that origin whenever you need the transformation to apply from a different origin.
Here you can see an example when the rotation is done from the top left corner. Without the origin modification, it would rotate around its center.
Note: You can set the transform-origin even outside the element
I am making a website and on most websites it has a big image with massive text in it which says Welcome or something I have replicated the same thing but I was wondering is the image in the photo behind the OptimisePCs possible to achieve with plain CSS so no image, this is for performance reasons because people have to download the image to see it which takes time.
SVG
Here is an svg solution.
By setting the width to 100% on the svg element is scales with the page in the horizontal/x direction.
In other words this background is responsive.
Added the menu for fun.
body {
margin: 0;
}
.content {
width: 100%;
}
/* SVG background */
.svg-background {
width: 100%;
height: 100%;
}
.svg-background polygon:nth-child(1) {
fill: #005A50;
stroke: #005A50;
stroke-width: 0.1;
}
.svg-background polygon:nth-child(2) {
fill: #007367;
}
.svg-background polygon:nth-child(3) {
fill: #1C9F91;
stroke: #1C9F91;
stroke-width: 0.1;
}
.svg-background polygon:nth-child(4) {
fill: #3DAEA2;
}
/* NAVBAR Many for making it look better :D*/
.navigation {
background-color: #222;
}
.menu-bar {
display: block;
list-style: none;
margin: 0;
padding: 0;
height: 50px;
}
.menu-bar li {
display: inline-block;
color: white;
font-size: 20px;
//dding: 15px;
padding-right: 15px;
padding-left: 15px;
line-height: 2em;
height: 100%;
}
.menu-bar li:hover {
background-color: #72B1D7;
}
<nav class="navigation">
<ul class="menu-bar">
<li>OptimisePCs</li>
<li>Home</li>
<li>About</li>
<li>Services</li>
</ul>
</nav>
<div class="content">
<svg class="svg-background" viewBox="0 0 100 100">
<polygon points="0,0 10,0 0,20" />
<polygon points="10,0 0,20 0,100 50,100" />
<polygon points="10,0 50,100 70,100 80,0" />
<polygon points="80,0 70,100 100,100 100,0" />
</svg>
</div>
It seems like what you want is a background.
You can achieve this with multiple backgrounds and CSS linear-gradient values at various angles. You can use color stops which go from solid to transparent at the same spot to get the hard edges.
Here's an example:
header{
width: 100%;
height: 200px;
background: linear-gradient(60deg, #227766 25%, rgba(0,0,0,0) 25%),
linear-gradient(350deg, #40D2B3 20%, rgba(0,0,0,0) 20%),
linear-gradient(125deg, rgba(0,0,0,0) 70%, #39C1A5 70%),
linear-gradient(125deg, #2D9D87 45%, rgba(0,0,0,0) 45%),
linear-gradient(125deg, #35BEA2 70%, rgba(0,0,0,0) 70%);
}
<header></header>
As an added bonus, this is responsive out of the box. It will scale with the size of the container.
Additionally, you should set a solid background-color which will be the fallback for older browsers which lack support for gradients.
In this case using a svg might be more space efficient (and also scales to any resolution)
To use it in "pure CSS", you can inline the svg:
.selector { background: url('data:image/svg+xml;base64, ... svg code goes here ...'); }
Personally I use SCSS and the compass framework to make this easy:
.selector { background: inline-image("path/to/file.svg"); }
The drawback is that you have to take care not to inline it multiple times (or you replicate the code), if you need to do that, combine the respective classes instead:
.selector1, .selector2 { background: url('data:image/svg+xml;base64, ... svg code goes here ...'); }
image to css
using this site you can easily change image to css + !!
<style>
.pixels{
border-radius: 0;
display: inline-block;
width: 1px;
height: 1px;
box-shadow: bla~~
}
</style>
<div class="pixels"></div>
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]);
}
"
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">