It's easy to create a rainbow in CSS using linear-gradient.
#grad1 {
height: 200px;
background: linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet, red);
}
<div id="grad1"></div>
But look at it! This gradient is aesthetically horrifying. It's streaky, there's ugly strips of pure colour where the endpoints meet, it doesn't loop very well, it's not smooth, and the colours clearly contrast against each other when they should seamlessly blend.
In short: it's a terrible gradient.
I'd like to find the perfect gradient. One that encompasses the rainbow in a slick, smooth way, one that doesn't leave any obvious bumps or visual tearing. Instead of a spiky mess, this gradient is a smooth curve.
Does this gradient exist?
You need to choose colors that will blend nicely together and more color steps.
background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
.rainbow-box {
width: 80vw;
height: 200px;
border-radius: 5px;
background: linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 154, 0, 1) 10%,
rgba(208, 222, 33, 1) 20%,
rgba(79, 220, 74, 1) 30%,
rgba(63, 218, 216, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(28, 127, 238, 1) 60%,
rgba(95, 21, 242, 1) 70%,
rgba(186, 12, 248, 1) 80%,
rgba(251, 7, 217, 1) 90%,
rgba(255, 0, 0, 1) 100%
);
}
<div class="rainbow-box"></div>
I made it using CSS gradient generator:
https://cssgradient.io/
You can get something that looks better by overlaying the individual red, green, and blue colours, trying to match the human colour cone sensitivities.
Here's an example, but it could be improved by adjusting some of the % numbers in the linear-gradients, and by having smother gradient shapes (currently triangles with cut-off tops).
<!DOCTYPE html>
<html>
<head>
<title>Rainbow</title>
<meta charset="UTF-8" />
<style>
* { box-sizing: border-box; }
.separate { width: 100%; height: 10em; }
.separate>* { width: 100%; height: 100%; margin-top: 1em; }
.overlay { width: 100%; height: 10em; filter: brightness(3); }
.overlay>* { width: 100%; height: 100%; position: absolute; }
.overlay>:nth-of-type(1) { opacity: 1; }
.overlay>:nth-of-type(2) { opacity: .5; }
.overlay>:nth-of-type(3) { opacity: .33; }
.overlay>:nth-of-type(4) { opacity: .25; }
.blue { background: linear-gradient(
90deg, rgb(0,0,256) 0%, rgb(0,0,256) 5%, rgb(0,0,0) 20% ); }
.green { background: linear-gradient(
90deg, rgb(0,0,0) 0%, rgb(0,256,0) 25%, rgb(0,256,0) 35%, rgb(0,0,0) 55% ); }
.red { background: linear-gradient(
90deg, rgb(0,0,0) 15%, rgb(256,0,0) 35%, rgb(256,0,0) 45%, rgb(0,0,0) 100% ); }
.blue2 { background: linear-gradient(
90deg, rgb(0,0,0) 65%, rgb(0,0,256) 95%, rgb(0,0,256) 100% ); }
</style>
</head>
<body>
<h1>Rainbow</h1>
<div class="overlay">
<div class="blue"></div>
<div class="green"></div>
<div class="red"></div>
<div class="blue2"></div>
</div>
<div class="separate">
<div class="blue"></div>
<div class="green"></div>
<div class="red"></div>
<div class="blue2"></div>
</div>
</body>
</html>
"Rainbow" or "Color wheel" is often referred to as Hue.
CSS has the hsl() function (stands for Hue, Saturation, Lightness).
To create the gradients, simply divide the 360 hue degrees by 12 main colors (= 30 deg. steps).
Apply increments on the Hue by 30 degrees:
#hue {
height: 40px;
background: linear-gradient(90deg,
hsl(0, 100%, 50%),
hsl(30, 100%, 50%),
hsl(60, 100%, 50%),
hsl(90, 100%, 50%),
hsl(120, 100%, 50%),
hsl(150, 100%, 50%),
hsl(180, 100%, 50%),
hsl(210, 100%, 50%),
hsl(240, 100%, 50%),
hsl(270, 100%, 50%),
hsl(300, 100%, 50%),
hsl(330, 100%, 50%),
hsl(360, 100%, 50%)
);
}
<div id="hue"></div>
I’m not a CSS programmer, but just using the linear gradient fill in MS Word/Excel/PowerPoint, I like to create my rainbow with just the following 4 RGB colors:
(255,0,0) ; (255,255,0) ; (0,192,255) ; (192,0,255).
That looks pretty good to me, and with very little effort! {See Images >>}
Another variation of the rainbow above is “Sunset over the Ocean”. (It will make a great background for a webpage). Start with the rainbow, replace the last (purple) color with the following dark blue one: (60,70,200). Then move the yellow slider right up against the light blue one (mine is at 60% and 61%). And that’s it! {See Image >>}
I managed to do it in CSS! :-) >>
.Rainbow-4Color-Mix
{ width:200px; height:350px;
background: linear-gradient(180deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 255, 0, 1) 33%,
rgba(0, 192, 255, 1) 66%,
rgba(192, 0, 255, 1) 100%);
}
.Gap {width:200px; height:50px; background-color:white;}
.Ocean-Sunset
{ width:200px; height:350px;
background: linear-gradient(180deg,
rgba(255, 0, 0, 1) 0%,
rgba(255, 255, 0, 1) 60%,
rgba(0, 192, 255, 1) 61%,
rgba(60, 70, 200, 1) 100%);
}
<div class="Rainbow-4Color-Mix"></div>
<div class="Gap"></div>
<div class="Ocean-Sunset"></div>
Just an idea: Instead of explicitly specifying all of the colors in the rainbow, you could just specify red, yellow, and blue. The colors should then just blend naturally.
Another idea: If you don't like these particular shades of yellow, red, and blue, you could try custom ones with RGB values. The basic idea is the same though with only using the three primary colors in the rainbow.
EDIT: You can add violet back in by adding red at the end.
#grad1 {
height: 200px;
background: linear-gradient(45deg, red, yellow, blue, red);
}
<div id="grad1"></div>
Related
I want stripes over gradient background. See the image below for stripes pattern. My gradient background is as follows :
background-image: linear-gradient(90deg, hsla(209, 33%, 82%, 1), rgb(240,240,240), hsla(37, 33%, 85%, 1));
If you observe bottom part of the image, you would find no Stripes and more gradiant. Stripes should be in only above part of the background.
Set the gradient on the div
Set the stripes on a pseudo
set a mask on this pseudo, going from opaque to transparent
.test {
background-image: linear-gradient(90deg, hsla(209, 33%, 82%, 1), rgb(240,240,240), hsla(37, 33%, 85%, 1));
width: 100%;
height: 400px;
position: relative;
}
.test:after {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
-webkit-mask-image: linear-gradient(rgba(0, 0, 0, 1.0) 10%, transparent 80%);
mask-image: linear-gradient(rgba(0, 0, 0, 1.0) 10%, transparent 80%);
background-image: repeating-linear-gradient(45deg, white 0px, white 10px, lightblue 10px, lightblue 20px);
}
<div class="test"></div>
Based on the color combination, this is what I could achieve, I guess this may help you to get started:
You have to change the angle to 45deg.
I hope this helps you:
.stripe {
width: 800px;
height: 900px;
background-image: linear-gradient(to top, #dadee0 20px, rgba(125, 168, 196, 0.5)), repeating-linear-gradient(45deg, hsla(209, 33%, 82%, 1), rgb(240, 240, 240) 100px, hsla(37, 33%, 85%, 1) 50px);
}
<h2 class="stripe"></h2>
.stripe {
width: 500px;
height: 700px;
background-image: repeating-linear-gradient(45deg, hsla(209, 33%, 82%, 1), rgb(240, 240, 240) 100px, hsla(37, 33%, 85%, 1) 100px);
}
<h2 class="stripe"></h2>
Or
something like this:
.stripe {
width: 50%;
height: 700px;
margin: 50 auto;
background: repeating-linear-gradient( 45deg, #83ABC6 0px, #83ABC6 50px, #9BBBCF 50px, #9BBBCF 100px);
}
<h2 class="stripe"></h2>
enjoy
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 500px;
height: 500px;
background-image: repeating-linear-gradient(
45deg,
transparent,
transparent 50px,
rgba(0, 0, 0, 0.1) 50px,
rgba(0, 0, 0, 0.1) 100px
),
linear-gradient(
0deg,
#c8d5e2,
#7da9c4
);
}
</style>
</head>
<body>
<div>
content
</div>
</body>
</html>
now try this code [EDIT]
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 250px;
height: 600px;
background-image: linear-gradient(
0deg,
#dadee0,
rgba(126, 169, 196, 0.5)
), repeating-linear-gradient(
45deg,
transparent,
transparent 50px,
rgba(0, 0, 0, 0.05) 50px,
rgba(0, 0, 0, 0.05) 100px
);
}
</style>
</head>
<body>
<div>
content
</div>
</body>
</html>
for the latest image [EDIT]
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 600px;
height: 400px;
background-image: linear-gradient(
0deg,
#dadee0 200px,
rgba(126, 169, 196, 0.5)
), repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(0, 0, 0, 0.05) 10px,
rgba(0, 0, 0, 0.05) 20px
);
}
</style>
</head>
<body>
<div>
</div>
</body>
</html>
I'm trying to get a background color on part of some tds, so that it looks similar to a progress bar background:
From left to somewhere in the middle, it's colored, and after that percentage, it's white.
And if it's 100%, of course, the whole td is colored.
The color, a linear-gradient, is the same on all tds, but the length will differ. I only have 3 lengths:
30%
70%
100%
Also 0%, but it's just empty then, so this is out of the question
For this, I'm using a specific class for each variation, .progress_**.
Every class has two linear-gradients on the background property.
This is my current working CSS:
.progress_30 {
background:
linear-gradient(to right,
rgba(0, 0, 0, 0) 0%,
rgba(255, 255, 255, 0) 30%,
rgba(255, 255, 255, 1) 30%
),
linear-gradient(to right, yellow, green)
;
}
.progress_70 {
background:
linear-gradient(to right,
rgba(0, 0, 0, 0) 0%,
rgba(255, 255, 255, 0) 70%,
rgba(255, 255, 255, 1) 70%
),
linear-gradient(to right, yellow, green)
;
}
.progress_100 {
background:
linear-gradient(to right,
rgba(0, 0, 0, 0) 0%,
rgba(255, 255, 255, 0) 100%,
rgba(255, 255, 255, 1) 100%
),
linear-gradient(to right, yellow, green)
;
}
As you can see, there is a lot that repeats.
I want at least to put the color in a separate .progress class, so it can be changed easily without altering the lengths, and so I can add or alter some lengths without touching the colors in the future.
So I tried this:
.progress {
background: linear-gradient(to right, yellow, green);
}
.progress_30 {
background:
linear-gradient(to right,
rgba(0, 0, 0, 0) 0%,
rgba(255, 255, 255, 0) 30%,
rgba(255, 255, 255, 1) 30%
)
;
}
.progress_70 {
background:
linear-gradient(to right,
rgba(0, 0, 0, 0) 0%,
rgba(255, 255, 255, 0) 70%,
rgba(255, 255, 255, 1) 70%
)
;
}
.progress_100 {
background:
linear-gradient(to right,
rgba(0, 0, 0, 0) 0%,
rgba(255, 255, 255, 0) 100%,
rgba(255, 255, 255, 1) 100%
)
;
}
This doesn't fully work: the white part on the right is the correct length. But on the left, I don't see my linear-gradient, only the page's background color (which isn't white).
Is there a way I can get as few repetitions as possible in CSS, at least have the linear-gradient's color set only once, or do I have to do it like in my first example?
You can rely on background-size and keep the gradient declaration within the same class:
div {
min-height: 50px;
}
.progress {
background:
linear-gradient(#fff, #fff) right no-repeat,
linear-gradient(to right, yellow, green);
}
.progress_30 {
background-size: 70% 100%, auto;
}
.progress_70 {
background-size: 30% 100%, auto;
}
.progress_100 {
background-size: 0% 100%, auto;
}
<div class="progress progress_30"></div>
<div class="progress progress_70"></div>
<div class="progress progress_100"></div>
You can simplify more using CSS variable in case you want to consider more percentage values:
div {
min-height: 50px;
}
.progress {
background:
linear-gradient(#fff, #fff) right/calc(100% - var(--p,50%)) 100% no-repeat,
linear-gradient(to right, yellow, green);
}
<div class="progress" style="--p:30%"></div>
<div class="progress" style="--p:68%"></div>
<div class="progress" style="--p:80%"></div>
<div class="progress" ></div>
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 want to create a checkerboard pattern using gradients. I've found an example and modified it to my needs, however it only works with -moz prefix. When I remove the -moz prefix, the pattern is completely different.
How can I make this -moz checkerboard pattern work with unprefixed linear-gradient?
body {
background-image:
linear-gradient(45deg, #808080 25%, transparent 25%),
linear-gradient(-45deg, #808080 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #808080 75%),
linear-gradient(-45deg, transparent 75%, #808080 75%);
background-size:20px 20px;
background-position:0 0, 10px 0, 10px -10px, 0px 10px;
}
Just modify the background-position like in the below snippet to get the required output. This works fine in Firefox, Chrome, Opera, IE11 and Edge.
body {
background-image: linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}
The problem seems to be happening because of a difference in the way the angles are handled by the -moz linear gradient and the standard one. -45deg in the -moz linear gradient seems to be equal to 135deg in the standard gradient (but changing the angle is resulting in a strange dot in the middle).
The below screenshots show the difference (both taken in the latest Firefox v44.0).
Output with -moz-linear-gradient:
Output with linear gradient:
It's 2020 and this can now be created with a single CSS gradient (if you don't need to support IE/ pre-Chromium Edge).
html {
background:
repeating-conic-gradient(#808080 0% 25%, transparent 0% 50%)
50% / 20px 20px
}
I wrote a detailed explanation on CSS Tricks for how this works.
The 45deg version works nicely, but can end up showing a line between the triangles at different zoom levels or on retina screens. Depending on what browsers you need to support you can also use background-blend-mode: difference (Caniuse currently shows support nearly everywhere except IE), you can tint the checks using an additional background image:
body {
background-image: /* tint image */
linear-gradient(to right, rgba(192, 192, 192, 0.75), rgba(192, 192, 192, 0.75)),
/* checkered effect */
linear-gradient(to right, black 50%, white 50%),
linear-gradient(to bottom, black 50%, white 50%);
background-blend-mode: normal, difference, normal;
background-size: 2em 2em;
}
This was Chrome's implementation for when you opened an image with transparency for a while (though they later removed it in favor of just using a solid background).
body {
background-position: 0px 0px, 10px 10px;
background-size: 20px 20px;
background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee 100%),linear-gradient(45deg, #eee 25%, white 25%, white 75%, #eee 75%, #eee 100%);
}
Thanks Harry for the inspiration - here's an scss mixin to do that
#mixin checkers($size: 50px, $contrast: 0.07) {
$checkerColor: rgba(#000, $contrast);
$angle: 45deg;
$tp: 25%;
background-image: linear-gradient($angle, $checkerColor $tp, transparent $tp),
linear-gradient(-$angle, $checkerColor $tp, transparent $tp),
linear-gradient($angle, transparent 3 * $tp, $checkerColor 3 * $tp),
linear-gradient(-$angle, transparent 3 * $tp, $checkerColor 3 * $tp);
background-size: $size $size;
background-position: 0 0, 0 $size/2, $size/2 -1 * $size/2, -1 * $size/2 0;
}
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: