Related
Instead of falling back on SVG, I'd love to accomplish this with pure CSS.
There are a number of tutorials on clipped edges using a series of Linear Gradients, i.e.
background: linear-gradient(135deg, transparent 15px, blue 0) top left,
linear-gradient(-135deg, transparent 15px, blue 0) top right,
linear-gradient(-45deg, transparent 15px, blue 0) bottom right,
linear-gradient(45deg, transparent 15px, blue0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
And a diagonal "linear gradient" can also be accomplished quite easily, i.e.
background: linear-gradient(290deg, blue 50%, darkblue 50%);
Is there a way to combine these two techniques to get something like the box pictured below?
Edit: Internet Explorer compatibility would be great.
-webkit-clip-path
clip-path
Are not IE compatible to my knowledge.
You can define one transparent corner via background gradient. However, when you declare more than one, they paint over the transparency defined by the previous rule. In essence, they paint over each other.
A better solution is to use clip-path. For simple shapes, you can use clippy.
body {
background: black;
}
#gradients {
width: 200px;
height: 50px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0) 15px, rgba(255, 0, 0, 1) 0) top left, linear-gradient(-135deg, rgba(255, 255, 255, 0) 15px, rgba(255, 0, 0, 1) 0) top right, linear-gradient(-45deg, rgba(255, 255, 255, 0) 15px, rgba(255, 0, 0, 1) 0) bottom right, linear-gradient(45deg, rgba(255, 255, 255, 0) 15px, blue) bottom left;
}
#gradientsPaintover {
margin: 30px 0 0 0;
width: 200px;
height: 50px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0) 15px, rgba(0, 255, 0, 0.4) 0) top left, linear-gradient(-135deg, rgba(255, 255, 255, 0) 15px, rgba(0, 0, 255, 1) 0) top right;
}
#clip {
background: red;
margin: 30px 0 0 0;
width: 200px;
height: 50px;
-webkit-clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
}
<div id="gradients"></div>
<div id="gradientsPaintover"></div>
<div id="clip"></div>
Serg's answer was helpful in solving the problem, but I thought'd I'd post a complete solution.
background: linear-gradient(290deg, blue 50%, darkblue 50%);
-webkit-clip-path: polygon(5% 0, 95% 0, 100% 10%, 100% 90%, 95% 100%, 5% 100%, 0 90%, 0 10%);
clip-path: polygon(5% 0, 95% 0, 100% 10%, 100% 90%, 95% 100%, 5% 100%, 0 90%, 0 10%);
A note that this will not work at all in IE and you should pursue the SVG option in that case.
Edit: spending some more time with this, there's no reason you couldn't create pseudo elements before and after your div that contains a linear-gradient to add the 'cut edge' look.
See codepen here or CSS below.
/*div and interior BG*/
div {
width: 80%;
height: 300px; /*Make sure your content has a height specified*/
display: inline-block;
background: linear-gradient(290deg, blue 50%, darkblue 50%);
position: relative;
margin-left: 10%;
}
/*Shared styles across pseudo elements*/
div:before, div:after {
content: '';
width: 20%;
min-height: 300px; /*Fits psuedo element height to content*/
position: absolute;
display:inline-block;
}
/*Position and cuts for left side*/
div:before {
left: -9.9%;
background: linear-gradient(135deg, transparent 15px, darkblue 0) top left,
linear-gradient(45deg, transparent 15px, darkblue 0) bottom left;
background-size: 100% 51%;
background-repeat: no-repeat;
}
/*Position and cuts for left right*/
div:after {
right: -9.9%;
background:
linear-gradient(-135deg, transparent 15px, blue 0) top right,
linear-gradient(-45deg, transparent 15px, blue 0) bottom right;
background-size: 100% 51%;
background-repeat: no-repeat;
}
I've got a semi-circular radial-gradient working here: http://codepen.io/Inlesco/pen/bpgbKN?editors=1100
Gradient styles:
.el:after {
content: '\00a0';
background: radial-gradient(at 50% 0%, red 0%, rgba(0,0,0,0.2) 0%, transparent 70%);
background-size: 100% 30px;
background-repeat: no-repeat;
float:left;
width:100%;
}
The pen uses CSS. However, if you set a CSS preprocessor (LESS/SASS), no gradient is created as, fe., Chrome marks it as invalid (seen when inspecting).
And if I place the same code (HTML / CSS from CodePen) to a local file (CSS in body <style>), no gradient is created either.
How come it works in web code editors like CodePen, but only without any CSS preprocessors? Is the output of them somehow different for radial-gradient?
When compiled with Sass (SCSS), I get the following result:
.el:after {
content: '\00a0';
background: radial-gradient(at 50% 0% at 50% 0%, #ff0000 0%, rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0) 70%);
background-size: 100% 30px;
background-repeat: no-repeat;
float: left;
width: 100%;
}
Sites like Codepen and Sassmeister don't compile with Sass, they compile with Compass (which is Sass with a bunch of extra stuff added to it).
Compass provides a function called radial-gradient (along with linear-gradient) that does a bunch of fancy stuff underneath the hood when combined with the background and background-image mixins to generate prefixes and inline SVGs for you.
Certain versions of Compass have a bug where they'll generate an invalid radial-gradient when you omit the optional shape argument. You just need to add it:
.el:after {
content: '\00a0';
background: radial-gradient(ellipse at 50% 0%, #ff0000 0%, rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0) 70%);
// ^ added `ellipse` here
background-size: 100% 30px;
background-repeat: no-repeat;
float: left;
width: 100%;
}
See: https://github.com/Compass/compass/issues/1937
Maybe you are declaring the LESS syntax in an incorrect manner. Try this,
.el {
margin: 0 auto;
width: 6em;
text-align:center;
font-size:30px;
&::after {
content: '\00a0';
background: radial-gradient(at 50% 0%, red 0%, rgba(0,0,0,0.2) 0%, transparent 70%);
background-size: 100% 30px;
background-repeat: no-repeat;
float:left;
width:100%;
}
}
I have been seeing a lot of new websites that have a zigzagged border in between an image and a div. When you open the image in a new tab the zigzag is not there, so it was created either with CSS3 or HTML5. Does anyone know how it is done?
Here are some examples:
http://themeforest.net/item/hungry-a-onepage-html-restaurant-template/full_screen_preview/9855248ref=freshdesignweb
http://designwp.com/yummie/brown/index.html
Wait for them to load.
zig zag borders are made using linear-gradient
50% is the blur
315deg is the rotation of right side
45deg is the rotation of left side
background size is the width and placement of the triangle
div {
width: 100%;
height: 50px;
background-size: 25px 120%;
background-image: linear-gradient(315deg, red 50%, rgba(0, 0, 0, 0) 50%),
linear-gradient(45deg, red 50%, black 50%);
}
<div></div>
you can also change the angle of rotation by changing the deg values
div {
width: 100%;
height: 50px;
background-size: 25px 150%;
background-image: linear-gradient(297deg, red 50%, rgba(0, 0, 0, 0) 50%),
linear-gradient(63deg, red 50%, black 50%);
}
<div></div>
First one is built with repeatable background image, and secound one with :before pseudo element:
.ss-style-top::before {
position: absolute;
content: '';
left: 0;
width: 100%;
height: 30px;
background-size: 25px 100%;
top: 0;
background-image: linear-gradient(315deg, #FFF 50%, transparent 50%),
linear-gradient(45deg, #FFF 50%, transparent 50%);
margin-top: -30px;
z-index: 100;
}
Here is the link of background image from first example: http://www.cssvillain.com/hungry/images/assets/parallax-bottom-alt.png
Why can't you create a checkered background using something like this?
background-color:#ccc;
background-image:linear-gradient(90deg, transparent 50%, #aaa 50%),
linear-gradient(90deg, #aaa 50%, #ccc 50%);
background-size:50px 50px,50px 50px;
background-position:0 0, 0 25px;
The idea is to layer the alternating colors on the bottom of a striped square. It doesn't work but it seems like it should.
Here is an exact replica of what a checkered background looks in a graphic design editor like Photoshop or Illustrator. (ALL CSS)
.checkered{
height: 240px;
background: -webkit-linear-gradient(45deg, rgba(0, 0, 0, 0.0980392) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.0980392) 75%, rgba(0, 0, 0, 0.0980392) 0), -webkit-linear-gradient(45deg, rgba(0, 0, 0, 0.0980392) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.0980392) 75%, rgba(0, 0, 0, 0.0980392) 0), white;
background: -moz-linear-gradient(45deg, rgba(0, 0, 0, 0.0980392) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.0980392) 75%, rgba(0, 0, 0, 0.0980392) 0), -moz-linear-gradient(45deg, rgba(0, 0, 0, 0.0980392) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.0980392) 75%, rgba(0, 0, 0, 0.0980392) 0), white;
background: linear-gradient(45deg, rgba(0, 0, 0, 0.0980392) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.0980392) 75%, rgba(0, 0, 0, 0.0980392) 0), linear-gradient(45deg, rgba(0, 0, 0, 0.0980392) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.0980392) 75%, rgba(0, 0, 0, 0.0980392) 0), white;
background-repeat: repeat, repeat;
background-position: 0px 0, 5px 5px;
-webkit-transform-origin: 0 0 0;
transform-origin: 0 0 0;
-webkit-background-origin: padding-box, padding-box;
background-origin: padding-box, padding-box;
-webkit-background-clip: border-box, border-box;
background-clip: border-box, border-box;
-webkit-background-size: 10px 10px, 10px 10px;
background-size: 10px 10px, 10px 10px;
-webkit-box-shadow: none;
box-shadow: none;
text-shadow: none;
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
-webkit-transform: scaleX(1) scaleY(1) scaleZ(1);
transform: scaleX(1) scaleY(1) scaleZ(1);
}
You can see a working example in my pen here
This implementation yields a checkered background on Chrome, Firefox and Safari:
body {
background-image:
linear-gradient(45deg, #000 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #000 75%),
linear-gradient(45deg, transparent 75%, #000 75%),
linear-gradient(45deg, #000 25%, #fff 25%);
background-size:100px 100px;
background-position:0 0, 0 0, -50px -50px, 50px 50px;
}
This style defines a four part background image. Each linear-gradient defines a black triangle. The triangles are shifted so that they align to form squares (two triangles each). The last linear-gradient defines the color of the other two squares (the negative space). The positioning of the third and fourth triangle is what makes it work. (They would otherwise be positioned on top of the other two similar styles.) See the result in the fiddles provided (for a better understanding replace #000 with four different colors and change #fff to transparent):
http://jsfiddle.net/1o0f34hp
Applied to a div:
http://jsfiddle.net/1o0f34hp/1
However there does seem to be some tearing along the edges between triangles in the Firefox. This artifact is referenced here:
background image, linear gradient jagged edged result needs to be smooth edged
I've also implemented this as a React styled-component as follows:
let dark = '#777';
let light = '#ccc';
export const Checkerboard = styled.div`
background-image: linear-gradient(45deg, ${dark} 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, ${dark} 75%),
linear-gradient(45deg, transparent 75%, ${dark} 75%),
linear-gradient(45deg, ${dark} 25%, ${light} 25%);
background-size: ${props => `${props.size} ${props.size}`};
background-position: 0 0, 0 0,
${props =>
`calc(${props.size} / -2) calc(${props.size} / -2), calc(${
props.size
} / 2) calc(${props.size} / 2)`};
`;
After a lot of playing around and trying to do this in other ways I actually understood what you wanted to do :-). And you were actually very close. You had one single problem: Both your gradients have 90deg, so they covered each other. Also there's no need for the background color since the gradient in the back does not have any transparency and it covers everything.
html {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background-image:linear-gradient(0deg, transparent 50%, #aaa 50%),
linear-gradient(90deg, #aaa 50%, #ccc 50%);
background-size:50px 50px,50px 50px;
background-position:0 0, 0 25px;
}
Also see this great post for how to create a proper checkerboard: http://lea.verou.me/2011/02/checkerboard-pattern-with-css3/
I made this simplified version. Set color & size in root properties in CSS.
:root {
--checker-color-1: #abcedf;
--checker-color-2: #123456;
--checker-size: 20px;
--checker-gradient: linear-gradient(45deg, var(--checker-color-1) 25%, transparent 25%, transparent 75%, var(--checker-color-1) 75%);
}
body {
background-color: var(--checker-color-2);
background-image: var(--checker-gradient), var(--checker-gradient);
background-position: 0 0, var(--checker-size) var(--checker-size);
background-size: calc(var(--checker-size) * 2) calc(var(--checker-size) * 2);
}
<!DOCTYPE html>
<html>
<head>
<title>CSS Checkered Background</title>
<meta charset="utf-8">
</head>
<body>
</body>
</html>
Updates:
This snippet was derived from CSS Checkered Background which shows a few more options.
But I have also since learned a new way of achieving the same effect, but it uses SVG (as well as JavaScript to create the SVG) SVG Checkered Background. Each method though has its own caveats.
Here is another tweak on this design but on a bias.
Please note that the background-size is important to keep a smooth transition in this pattern.
html {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background:repeating-linear-gradient(135deg, rgba(0,64,101,0.7) 40%, #004065 60%),
repeating-linear-gradient(45deg, rgba(0,80,126,0.7) 40%, #004065 60%);
background-size:12px 18px;
background-position: 0 0;
}
To change the color of the background, alter the second hex color in both repeating linear gradients.
Hope this helps someone
While the previous answers show that it is possible, in most cases it's probably better to use an actual background image.
A 10x10 PNG checker image is around 80 bytes.
That is 108 bytes base64-encoded, and 148 bytes for the complete CSS rule - less than the shortest pure-CSS solution.
A 2x2 PNG image is not much smaller, but needs additional CSS for scaling and rendering.
The best solution I came up with is to use conic-gradient(). This also avoids the artifacts produced by linear-gradient() with 45deg.
function setVar(name, value) {
document.getElementById('checkered').style.setProperty(name, value);
}
.checkered {
--color-1: #808080;
--color-2: #a9a9a9;
--size: 8px;
background-image: conic-gradient(var(--color-1) 25%, var(--color-2) 25%, var(--color-2) 50%, var(--color-1) 50%, var(--color-1) 75%, var(--color-2) 75%);
background-size: calc(var(--size)*2) calc(var(--size)*2);
}
input {
margin: 4px;
height: 32px;
box-sizing: border-box;
border: 2px solid lightgray;
border-radius: 4px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Checkered Background Image (Pure CSS)</title>
</head>
<body style="margin:0; width:100vw; height:100vh;">
<div id="checkered" class="checkered" style="width:100%; height:100%; padding: 20px; box-sizing:border-box; display:flex; align-items:start;">
<div style="background-color:white; padding:8px; border-radius:9px; display:flex;">
<input type="color" name="color-1" value="#808080" oninput="setVar('--color-1', this.value)">
<input type="color" name="color-2" value="#a9a9a9" oninput="setVar('--color-2', this.value)">
<input type="number" name="size" min="1" value="8" oninput="setVar('--size', this.value + 'px')">
</div>
</div>
</body>
</html>
I made a checkerboard pattern based on 10x10 squares in the Terminal with ImageMagick like this:
magick -size 10x10 xc:"gray(154)" xc:"gray(102)" +append \( +clone -flop \) -append -strip checkerboard.png
That looks like this:
Now, if I want the base64 representation I can do:
magick -size 10x10 xc:"gray(154)" xc:"gray(102)" +append \( +clone -flop \) -append -strip png:- | base64
That gives this:
iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAAAAACo4kLRAAAAH0lEQVQY02OcxQADZ+AsJgYsYKgIsiD8YTJInEShIAA1NwKQeKc4/QAAAABJRU5ErkJggg==
which is just 120 characters!!!
Then I can use that for the repeating background like this:
<div style="background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAAAAACo4kLRAAAAH0lEQVQY02OcxQADZ+AsJgYsYKgIsiD8YTJInEShIAA1NwKQeKc4/QAAAABJRU5ErkJggg==)">'
And if I put a red <img> with a gradient transparency, on that background, I get:
I'm trying to get a background for some text that is dual-tone, or the top half is one color and the bottom half is another. I have attached a link to a picture of what this should look like. Any ideas on how I can achieve this? Thanks, in advance, for the help!
Michael
http://michaelphillips.dropmark.com/12339/296433
Three ways come to mind:
One: Most Cross Browser (CSS1): Make a 1px wide image of the two colors, probably about 30px tall for each color, then
<span class="duoTone">wrap your text in a span</span>
and set the
.duoTone {background-image: url(path/to/your/img.jpg) left center repeat-x;}
Two: Less friendly to older browsers (CSS2): Same span wrapper as above but with this css (see fiddle).
.duoTone {
position: relative;
}
.duoTone:before,
.duoTone:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 50%;
z-index: -1;
background-color: #bbbbbb;
}
.duoTone:after {
top: auto;
bottom: 0;
background-color: #888888;
}
Three: Sleek, but only for newer browsers (CSS3): Same span code as #1 (see fiddle).
.duoTone {
background-color: #888888 ;
background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(.5, rgba(255, 255, 255, .4)), color-stop(.5, transparent), to(transparent));
background-image: -moz-linear-gradient(rgba(255, 255, 255, .4) 50%, transparent 50%, transparent);
background-image: -o-linear-gradient(rgba(255, 255, 255, .4) 50%, transparent 50%, transparent);
background-image: linear-gradient(rgba(255, 255, 255, .4) 50%, transparent 50%, transparent);
}