background – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Fri, 30 Sep 2022 17:30:36 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 background – CSS-Tricks https://css-tricks.com 32 32 45537868 CSS Checkerboard Background… But With Rounded Corners and Hover Styles https://css-tricks.com/css-checkerboard-background-but-with-rounded-corners-and-hover-styles/ https://css-tricks.com/css-checkerboard-background-but-with-rounded-corners-and-hover-styles/#comments Tue, 20 Sep 2022 13:19:24 +0000 https://css-tricks.com/?p=373167 On one hand, creating simple checkered backgrounds with CSS is easy. On the other hand, though, unless we are one of the CSS-gradient-ninjas, we are kind of stuck with basic patterns.

At least that’s what I thought while staring at …


CSS Checkerboard Background… But With Rounded Corners and Hover Styles originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
On one hand, creating simple checkered backgrounds with CSS is easy. On the other hand, though, unless we are one of the CSS-gradient-ninjas, we are kind of stuck with basic patterns.

At least that’s what I thought while staring at the checkered background on my screen and trying to round those corners of the squares just a little…until I remembered my favorite bullet point glyph — — and figured that if only I could place it over every intersection in the pattern, I’ll surely get the design I want.

Turns out it’s possible! Here’s the proof.

Let’s start with the basic pattern:

<div></div>
div {
 background: 
  repeating-linear-gradient(
    to right, transparent, 
    transparent 50px, 
    white 50px, 
    white 55px
  ),
  repeating-linear-gradient(
    to bottom, transparent,  
    transparent 50px, 
    white 50px, 
    white 55px
  ),
  linear-gradient(45deg, pink, skyblue);
  /* more styles */
}

What that gives us is a repeating background of squares that go from pink to blue with 5px white gaps between them. Each square is fifty pixels wide and transparent. This is created using repeating-linear-gradient, which creates a linear gradient image where the gradient repeats throughout the containing area.

In other words, the first gradient in that sequence creates white horizontal stripes and the second gradient creates white vertical stripes. Layered together, they form the checkered pattern, and the third gradient fills in the rest of the space.

Now we add the star glyph I mentioned earlier, on top of the background pattern. We can do that by including it on the same background property as the gradients while using an encoded SVG for the shape:

div {
  background: 
    repeat left -17px top -22px/55px 55px
    url("data:image/svg+xml,
    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
      <foreignObject width='35px' height='35px'>
        <div xmlns='http://www.w3.org/1999/xhtml' style='color: white; font-size: 35px'>✦</div>
      </foreignObject>
    </svg>"
    ), 
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      white 50px,
      white 55px
    ),
    linear-gradient(45deg, pink, skyblue);
  /* more style */
}

Let’s break that down. The first keyword, repeat, denotes that this is a repeating background image. Followed by that is the position and size of each repeating unit, respectively (left -17px top -22px/55px 55px). This offset position is based on the glyph and pattern’s size. You’ll see below how the glyph size is given. The offset is added to re-position the repeating glyph exactly over each intersection in the checkered pattern.

The SVG has an HTML <div> carrying the glyph. Notice that I declared a font-size on it. That ultimately determines the border radius of the squares in the checkerboard pattern — the bigger the glyph, the more rounded the squares. The unrolled SVG from the data URL looks like this:

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
  <foreignObject width='35px' height='35px'>
    <div xmlns='http://www.w3.org/1999/xhtml' style='color:white;font-size:35px'>✦</div>
  </foreignObject>
</svg>

Now that a CSS pattern is established, let’s add a :hover effect where the glyph is removed and the white lines are made slightly translucent by using rgb() color values with alpha transparency.

div:hover {
  background:
    repeating-linear-gradient(
      to right, transparent,
      transparent 50px,
      rgb(255 255 255 / 0.5) 50px,
      rgb(255 255 255 / 0.5) 55px
    ),
    repeating-linear-gradient(
      to bottom, transparent,
      transparent 50px,
      rgb(255 255 255 / 0.5) 50px,
      rgb(255 255 255 / 0.5) 55px
    ),
  linear-gradient(45deg, pink, skyblue);
  box-shadow: 10px 10px 20px pink;
}

There we go! Now, not only do we have our rounded corners, but we also have more control control over the pattern for effects like this:

Again, this whole exercise was an attempt to get a grid of squares in a checkerboard pattern that supports rounded corners, a background gradient that serves as an overlay across the pattern, and interactive styles. I think this accomplishes the task quite well, but I’m also interested in how you might’ve approached it. Let me know in the comments!


CSS Checkerboard Background… But With Rounded Corners and Hover Styles originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/css-checkerboard-background-but-with-rounded-corners-and-hover-styles/feed/ 4 373167
Cool Hover Effects That Use Background Properties https://css-tricks.com/cool-hover-effects-using-background-properties/ https://css-tricks.com/cool-hover-effects-using-background-properties/#comments Wed, 27 Apr 2022 14:20:07 +0000 https://css-tricks.com/?p=365383 A while ago, Geoff wrote an article about a cool hover effect. The effect relies on a combination of CSS pseudo-elements, transforms, and transitions. A lot of comments have shown that the same effect can be done using background …


Cool Hover Effects That Use Background Properties originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
A while ago, Geoff wrote an article about a cool hover effect. The effect relies on a combination of CSS pseudo-elements, transforms, and transitions. A lot of comments have shown that the same effect can be done using background properties. Geoff mentioned that was his initial thought and that’s what I was thinking as well. I am not saying the pseudo-element he landed on is bad, but knowing different methods to achieve the same effect can only be a good thing.

Cool Hover Effects series:

  1. Cool Hover Effects That Use Background Properties (you are here!)
  2. Cool Hover Effects That Use CSS Text Shadow
  3. Cool Hover Effects That Use Background Clipping, Masks, and 3D

In this post, we will re-work that hover effect, but also expand it into other types of hover effects that only use CSS background properties.

You can see the background properties at work in that demo, as well as how we can use custom properties and the calc() function to do even more. We are going to learn how to combine all of these so we are left with nicely optimized code!

Hover effect #1

Let’s start with the first effect which is the reproduction of the one detailed by Geoff in his article. The code used to achieve that effect is the following:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) var(--p, 0) / var(--p, 0) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
  color: #fff;
}

If we omit the color transition (which is optional), we only need three CSS declarations to achieve the effect. You are probably surprised how small the code is, but you will see how we got there.

First, let’s start with a simple background-size transition:

We are animating the size of a linear gradient from 0 100% to 100% 100%. That means the width is going from 0 to 100% while the background itself remains at full height. Nothing complex so far.

Let’s start our optimizations. We first transform our gradient to use the color only once:

background-image: linear-gradient(#1095c1 0 0);

The syntax might look a bit strange, but we are telling the browser that one color is applied to two color stops, and that’s enough to define a gradient in CSS. Both color stops are 0, so the browser automatically makes the last one 100% and fills our gradient with the same color. Shortcuts, FTW!

With background-size, we can omit the height because gradients are full height by default. We can do a transition from background-size: 0 to background-size: 100%.

.hover-1 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: 0;
  background-repeat: no-repeat;
  transition: .4s;
}
.hover-1:hover {
  background-size: 100%;
}

Let’s introduce a custom property to avoid the repetition of background-size:

.hover-1 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: var(--p, 0%);
  background-repeat: no-repeat;
  transition: .4s;
}
.hover-1:hover {
  --p: 100%;
}

We are not defining --p initially, so the fallback value (0% in our case) will be used. On hover, we define a value that replaces the fallback one ( 100%).

Now, let’s combine all the background properties using the shorthand version to get:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) left / var(--p, 0%) no-repeat;
  transition: .4s;
}
.hover-1:hover {
  --p: 100%;
}

We are getting closer! Note that I have introduced a left value (for the background-position) which is mandatory when defining the size in the background shorthand. Plus, we need it anyway to achieve our hover effect.

We need to also update the position on hover. We can do that in two steps:

  1. Increase the size from the right on mouse hover.
  2. Decrease the size from the left on mouse out.

To do this, we need to update the background-position on hover as well:

We added two things to our code:

  • A background-position value of right on hover
  • A transition-duration of 0s on the background-position

This means that, on hover, we instantly change the background-position from left (see, we needed that value!) to right so the background’s size will increase from the right side. Then, when the mouse cursor leaves the link, the transition plays in reverse, from right to left, making it appear that we are decreasing the background’s size from the left side. Our hover effect is done!

But you said we only needed three declarations and there are four.

That’s true, nice catch. The left and right values can be changed to 0 0 and 100% 0, respectively; and since our gradient is already full height by default, we can get by using 0 and 100%.

.hover-1 {
  background: linear-gradient(#1095c1 0 0) 0 / var(--p, 0%) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
  background-position: 100%;
}

See how background-position and --p are using the same values? Now we can reduce the code down to three declarations:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) var(--p, 0%) / var(--p,0%) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
}

The custom property --p is defining both the background position and size. On hover, It will update both of them as well. This is a perfect use case showing how custom properties can help us reduce redundant code and avoid writing properties more than once. We define our setting using custom properties and we only update the latter on hover.

But the effect Geoff described is doing the opposite, starting from left and ending at right. How do we do that when it seems we cannot rely on the same variable?

We can still use one variable and update our code slightly to achieve the opposite effect. What we want is to go from 100% to 0% instead of 0% to 100%. We have a difference of 100% that we can express using calc(), like this:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) calc(100% - var(--p,0%)) / var(--p,0%) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
}

--p will change from 0% to 100%, but the background’s position will change from 100% to 0%, thanks to calc().

We still have three declarations and one custom property, but a different effect.

Before we move to the next hover effect, I want to highlight something important that you have probably noticed. When dealing with custom properties, I am using 0% (with a unit) instead of a unit-less 0. The unit-less zero may work when the custom property is alone, but will fail inside calc() where we need to explicitly define the unit. I may need another article to explain this quirk but always remember to add the unit when dealing with custom properties. I have two answers on StackOverflow (here and here) that go into more detail.

Hover effect #2

We need a more complex transition for this effect. Let’s take a look at a step-by-step illustration to understand what is happening.

Diagram showing the hover effect in three pieces.
Initially, a fixed-height, full-width gradient is outside of view. Then we move the gradient to the right to cover the bottom side. Finally, we increase the size of the gradient from the fixed height to 100% to cover the whole element.

We first have a background-position transition followed by a background-size one. Let’s translate this into code:

.hover-2 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: 100% .08em; /* .08em is our fixed height; modify as needed. */
  background-position: /* ??? */;
  background-repeat: no-repeat;
  transition: background-size .3s, background-position .3s .3s;
}
.hover-2:hover {
  transition: background-size .3s .3s, background-position .3s;
  background-size: 100% 100%;
  background-position: /* ??? */;
}

Note the use of two transition values. On hover, we need to first change the position and later the size, which is why we are adding a delay to the size. On mouse out, we do the opposite.

The question now is: what values do we use for background-position? We left those blank above. The background-size values are trivial, but the ones for background-position are not. And if we keep the actual configuration we’re unable to move our gradient.

Our gradient has a width equal to 100%, so we cannot use percentage values on background-position to move it.

Percentage values used with background-position are always a pain especially when you use them for the first time. Their behavior is non-intuitive but well defined and easy to understand if we get the logic behind it. I think it would take another article for a full explanation why it works this way, but here’s another “long” explanation I posted over at Stack Overflow. I recommend taking a few minutes to read that answer and you will thank me later!

The trick is to change the width to something different than 100%. Let’s use 200%. We’re not worried about the background exceeding the element because the overflow is hidden anyway.

.hover-2 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: 200% .08em;
  background-position: 200% 100%;
  background-repeat: no-repeat;
  transition: background-size .3s, background-position .3s .3s;
}
.hover-2:hover {
  transition: background-size .3s .3s, background-position .3s;
  background-size: 200% 100%;
  background-position: 100% 100%;
}

And here’s what we get:

It’s time to optimize our code. If we take the ideas we learned from the first hover effect, we can use shorthand properties and write fewer declarations to make this work:

.hover-2 {
  background: 
    linear-gradient(#1095c1 0 0) no-repeat
    var(--p, 200%) 100% / 200% var(--p, .08em);
  transition: .3s var(--t, 0s), background-position .3s calc(.3s - var(--t, 0s));
}
.hover-2:hover {
  --p: 100%;
  --t: .3s;
}

We add all the background properties together using the shorthand version then we use --p to express our values. The sizes change from .08em to 100% and the position from 200% to 100%

I am also using another variable --t , to optimize the transition property. On mouse hover we have it set to a .3s value, which gives us this:

transition: .3s .3s, background-position .3s 0s;

On mouse out, --t is undefined, so the fallback value will be used:

transition: .3s 0s, background-position .3s .3s;

Shouldn’t we have background-size in the transition?

That is indeed another optimization we can make. If we don’t specify any property it means “all” the properties, so the transition is defined for “all” the properties (including background-size and background-position). Then it’s defined again for background-position which is similar to defining it for background-size, then background-position.

“Similar” is different than saying something is the “same.” You will see a difference if you change more properties on hover, so the last optimization might be unsuitable in some cases.

Can we still optimize the code and use only one custom property?

Yes, we can! Ana Tudor shared a great article explaining how to create DRY switching where one custom property can update multiple properties. I won’t go into the details here, but our code can be revised like this:

.hover-2 {
  background: 
    linear-gradient(#1095c1 0 0) no-repeat
    calc(200% - var(--i, 0) * 100%) 100% / 200% calc(100% * var(--i, 0) + .08em);
  transition: .3s calc(var(--i, 0) * .3s), background-position .3s calc(.3s - calc(var(--i, 0) * .3s));
}
.hover-2:hover {
  --i: 1;
}

The --i custom property is initially undefined, so the fallback value, 0, is used. On hover though, we replace 0 with 1. You can do the math for both cases and get the values for each one. You can see that variable as a “switch” that update all our values at once on hover.

Again, we’re back to only three declarations for a pretty cool hover effect!

Hover effect #3

We are going to use two gradients instead of one for this effect. We will see that combining multiple gradients is another way to create fancy hover effects.

Here’s a diagram of what we’re doing:

We initially have two gradients that overflow the element so that they are out of view. Each one has a fixed height and toes up half of the element’s width. Then we slide them into view to make them visible. The first gradient is placed at the bottom-left and the second one at the top-right. Finally, we increase the height to cover the whole element.

Here’s how that looks in CSS:

.hover-3 {
  background-image:
    linear-gradient(#1095c1 0 0),
    linear-gradient(#1095c1 0 0);
  background-repeat: no-repeat;
  background-size: 50% .08em;
  background-position:
    -100% 100%,
    200% 0;
  transition: background-size .3s, background-position .3s .3s;
}
.hover-3:hover {
  background-size: 50% 100%;
  background-position:
    0 100%,
    100% 0;  
  transition: background-size .3s .3s, background-position .3s;
}

The code is almost the same as the other hover effects we’ve covered. The only difference is that we have two gradients with two different positions. The position values may look strange but, again, that’s related to how percentages work with the background-position property in CSS, so I highly recommend reading my Stack Overflow answer if you want to get into the gritty details.

Now let’s optimize! You get the idea by now — we’re using shorthand properties, custom properties, and calc() to tidy things up.

.hover-3 {
  --c: no-repeat linear-gradient(#1095c1 0 0);
  background: 
    var(--c) calc(-100% + var(--p, 0%)) 100% / 50% var(--p, .08em),
    var(--c) calc( 200% - var(--p, 0%)) 0    / 50% var(--p, .08em);
  transition: .3s var(--t, 0s), background-position .3s calc(.3s - var(--t, 0s));
}
.hover-3:hover {
  --p: 100%;
  --t: 0.3s;
}

I have added an extra custom property, --c, that defines the gradient since the same gradient is used in both places.

I am using 50.1% in that demo instead of 50% for the background size because it prevents a gap from showing between the gradients. I also added 1% to the positions for similar reasons.

Let’s do the second optimization by using the switch variable:

.hover-3 {
  --c: no-repeat linear-gradient(#1095c1 0 0);
  background: 
    var(--c) calc(-100% + var(--i, 0) * 100%) 100% / 50% calc(100% * var(--i, 0) + .08em),
    var(--c) calc( 200% - var(--i, 0) * 100%) 0 / 50% calc(100% * var(--i, 0) + .08em);
  transition: .3s calc(var(--i, 0) * .3s), background-position .3s calc(.3s - var(--i, 0) * .3s);
}
.hover-3:hover {
  --i: 1;
}

Are you started to see the patterns here? It’s not so much that the effects we’re making are difficult. It’s more the “final step” of code optimization. We start by writing verbose code with a lot of properties, then reduce it following simple rules (e.g. using shorthand, removing default values, avoiding redundant values, etc) to simplify things down as much as possible.

Hover effect #4

I will raise the difficulty level for this last effect, but you know enough from the other examples that I doubt you’ll have any issues with this one.

This hover effect relies on two conic gradients and more calculations.

Initially, we have both gradients with zero dimensions in Step 1. We increase the size of each one in Step 2. We keep increasing their widths until they fully cover the element, as shown in Step 3. After that, we slide them to the bottom to update their position. This is the “magic” part of the hover effect. Since both gradients will use the same coloration, changing their position in Step 4 will make no visual difference — but we will see a difference once we reduce the size on mouse out during Step 5.

If you compare Step 2 and Step 5, you can see that we have a different inclination. Let’s translate that into code:

.hover-4 {
  background-image:
    conic-gradient(/* ??? */),
    conic-gradient(/* ??? */);
  background-position:
    0 0,
    100% 0;
  background-size: 0% 200%;
  background-repeat: no-repeat;
  transition: background-size .4s, background-position 0s;
}
.hover-4:hover {
  background-size: /* ??? */ 200%;
  background-position:
    0 100%,
    100% 100%;
}

The positions are pretty clear. One gradient starts at top left (0 0) and ends at bottom left (0 100%) while the other starts at top right (100% 0) and ends at bottom right (100% 100%).

We’re using a transition on the background positions and sizes to reveal them. We only need a transition value for the background-size. And like before, background-position needs to change instantly, so we’re assigning a 0s value for the transition’s duration.

For the sizes, both gradient need to have 0 width and twice the element height (0% 200%). We will see later how their sizes change on hover. Let’s first define the gradient configuration.

The diagram below illustrates the configuration of each gradient:

Note that for the second gradient (indicated in green), we need to know the height to use it inside the conic-gradient we’re creating. For this reason, I am going to add a line-height that sets the element’s height and then try that same value for the conic gradient values we left out.

.hover-4 {
  --c: #1095c1;
  line-height: 1.2em;
  background-image:
    conic-gradient(from -135deg at 100%  50%, var(--c) 90deg, #0000 0),
    conic-gradient(from -135deg at 1.2em 50%, #0000 90deg, var(--c) 0);
  background-position:
    0 0,
    100% 0;
  background-size: 0% 200%;
  background-repeat: no-repeat;
  transition: background-size .4s, background-position 0s;
}
.hover-4:hover {
  background-size: /* ??? */ 200%;
  background-position:
    0 100%,
    100% 100%;
}

The last thing we have left is to figure out the background’s size. Intuitively, we may think that each gradient needs to take up half of the element’s width but that’s actually not enough.

We’re left with a large gap if we use 50% as the background-size value for both gradients.

We get a gap equal to the height, so we actually need to do is increase the size of each gradient by half the height on hover for them to cover the whole element.

.hover-4:hover {
  background-size: calc(50% + .6em) 200%;
  background-position:
    0 100%,
    100% 100%;
}

Here’s what we get after optimizing them like the previous examples:

.hover-4 {
  --c: #1095c1;
  line-height: 1.2em;
  background:
    conic-gradient(from -135deg at 100%  50%, var(--c) 90deg, #0000 0) 
      0  var(--p, 0%) / var(--s, 0%) 200% no-repeat,
    conic-gradient(from -135deg at 1.2em 50%, #0000 90deg, var(--c) 0) 
      100% var(--p, 0%) / var(--s, 0%) 200% no-repeat;
  transition: .4s, background-position 0s;
}
.hover-4:hover {
  --p: 100%;
  --s: calc(50% + .6em);
}

What about the version with only one custom property?

I will leave that for you! After looking at four similar hover effects, you should be able to get the final optimization down to a single custom property. Share your work in the comment section! There’s no prize, but we may end up with different implementations and ideas that benefit everyone!

Before we end, let me share a version of that last hover effect that Ana Tudor cooked up. It’s an improvement! But note that it lacks Firefox supports due to a known bug. Still, it’s a great idea that shows how to combine gradients with blend modes to create even cooler hover effects.

Wrapping up

We made four super cool hover effects! And even though they are different effects, they all take the same approach of using CSS background properties, custom properties, and calc(). Different combinations allowed us to make different versions, all using the same techniques that leave us with clean, maintainable code.

If you want to get some ideas, I made a collection of 500 (yes, 500!) hover effects, 400 of which are done without pseudo-elements. The four we covered in this article are just the tip of the iceberg!


Cool Hover Effects That Use Background Properties originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/cool-hover-effects-using-background-properties/feed/ 6 365383
Grainy Gradients https://css-tricks.com/grainy-gradients/ https://css-tricks.com/grainy-gradients/#comments Mon, 13 Sep 2021 19:04:51 +0000 https://css-tricks.com/?p=351302 Browse through Dribbble or Behance, and you’ll find designers using a simple technique to add texture to an image: noise. Adding noise makes otherwise solid colors or smooth gradients, such as shadows, more realistic. But despite designers’ affinity for texture, …


Grainy Gradients originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Browse through Dribbble or Behance, and you’ll find designers using a simple technique to add texture to an image: noise. Adding noise makes otherwise solid colors or smooth gradients, such as shadows, more realistic. But despite designers’ affinity for texture, noise is rarely used in web design.

In this article, we’ll generate colorful noise to add texture to a gradient with only a small amount of CSS and SVG. Alright, let’s make some noise!

Illustration by Hank Washington on Behance
Illustration by Jordan Kay on Dribbble

Interactive playground

Check it out here. The quickest way to understand what’s happening is to play with the parameters that make up the layers.

The trick: SVG noise and CSS gradients

The core technique in this article is built on top of a Stack Overflow answer by Chris Pachl to the question: Can you add noise to a CSS gradient?

The trick is to use an SVG filter to create the noise, then apply that noise as a background. Layer it underneath a gradient, boost the brightness and contrast, and that’s it — you have gradient that gradually dithers away.

The key ingredients

Here’s what we’re working with under the hood:

  • SVG turbulence: This is our noise filter.
  • Background with gradient and SVG: Next, we drop that filter into CSS as a background image that combines the filter with a CSS gradient.
  • Boost brightness and contrast: Then we turn to CSS filter to increase the brightness and contrast of the noise.
  • Blend gradients: Finally, we optionally use mix-blend-mode to further filter out colors and blend gradients together.

Let’s go into detail on each of these parts.

Using SVG turbulence

Within the realm of SVG, we can define filters, and one such filter lets us create Perlin noise. It’s called <feTurbulence> and we can define attributes, such as whether it is “turbulence” or “noise” and how fine or coarse it is. Bence Szabó explains it in much more detail as he demonstrates how it can be used to create patterns.

<svg viewBox="0 0 200 200" xmlns='http://www.w3.org/2000/svg'>
  <filter id='noiseFilter'>
    <feTurbulence 
      type='fractalNoise' 
      baseFrequency='0.65' 
      numOctaves='3' 
      stitchTiles='stitch' />
  </filter>

  <rect width='100%' height='100%' filter='url(#noiseFilter)' />
</svg>

This SVG example creates a filter and renders a <rect> element that we can use for our grainy gradients. Notice that the SVG <filter> is defined separately from the <rect>, and the <rect> simply references it.

Play around with changing some of the properties of <feTurbulence>

We’re going to save this SVG as a separate file. We reference an external link to grab the SVG in the demos throughout in this article. In practice, though, you would reference a local file or your own CDN. It doesn’t work to reference the SVG by its id in CSS, for some quirky reason, but you can inline the SVG, as we show in the playground demo. We don’t do this in the demos for legibility reasons.

Creating a CSS background with SVG and a gradient

After we have the SVG file stored somewhere we can reference it by a URL or path, we can now use it in a CSS background, combined with a gradient.

.noise {
  /* ... */
  background:
    linear-gradient(to right, blue, transparent),
    url(https://grainy-gradients.vercel.app/noise.svg);
}

Order matters here. In this particular example, we want a solid color (i.e. no noise) to transition into noise and then into another color. We also want one end of the gradient to be transparent so that the noise shows through.

Like this:

However, this isn’t particularly nice because the noise is too muddled. We need to fray it and make it grainier. We can do that by…

Boosting the brightness and contrast

Adding a CSS filter makes the noise more stark, pushing the most faded colors towards white or black. The filter applies to the entire <div>, so the leftmost blue is a different blue than the pure blue we started with.

.noise {
  /* ... */
  background: 
    linear-gradient(to right, blue, transparent), 
    url(https://grainy-gradients.vercel.app/noise.svg);
  filter: contrast(170%) brightness(1000%);  
}

You can play around with how contrast and brightness affect the gradient. Boosting the brightness and contrast pushes out the muddled grays in the follow demo.

The noise is not uniform in color

If you zoom in, you’ll notice that the noise is made up of many colors. The SVG filter was colorful to begin with, and increasing the brightness and contrast emphasized certain colors. Although hardly noticeable, if this confetti is unwelcome, we can continue to filter out colors with CSS blending (i.e. mix-blend-mode and background-blend-mode ).

CSS blending

Let’s make a grainy gradient that transitions between two colors. CSS blending allows us to stack layers of color. In the next example, we’re adding another <div> to the markup, positioning it over the original gradient, then applying mix-blend-mode: multiply; to smooth things out.

<section>
  <div class="isolate">
    <div class="noise"></div>
    <div class="overlay"></div>
  </div>
</section>
.noise {
  /* ... */
  background: 
    linear-gradient(20deg, rebeccapurple, transparent), 
    url(https://grainy-gradients.vercel.app/noise.svg); 
  contrast(170%) brightness(1000%);
}
.overlay {
  /* ... */
  background: moccasin;
  mix-blend-mode: multiply;
}

We can use the CSS isolation property to create a new stacking context and choose what gets blended. If we were to leave out isolation in the next example, the gradient and overlay would blend with the background color. Try it in the Pen and comment out that line!

/* Same as before */

.isolate {
  isolation: isolate;
  /* ... */
}

Some use cases

We’ve looked at a pretty simple example of how to make a noisy gradient, but where might you use one? Let’s consider several use cases.

Light and shadows, with grain

Where do gradients naturally occur? Light and shadows, for one. We can take advantage of the CSS property mix-blend-mode to smoothly blend gradients and selectively filter the colors we want to see in the noise.

In the “shadow” example, we create a dark gradient, and invert it to create the effect in the “light” example. In both cases, mix-blend-mode allows us to blend it with other gradients.

Holographic foil

The drastic brightness and contrast boost creates a rainbow effect that’s reminiscent of holographic foil.

Taking things further

Try the playground and mess around with the different parameters to see how they affect the texture.

Beyond that, here are some ways to continue fiddling with this technique:

  • Use a different SVG: All of the gradients in this article use the same SVG, but you can toy with the parameters that generates the noise to adjust the coarseness as well as the look and feel in the playground.
  • Try different gradients: Besides linear-gradient, CSS offers four more types of gradients. Can you name them? (Here’s one.)
  • Add more layers: With CSS blending, you can stack as many any layers as you’d like and blend them down.
  • Apply different SVG filters: There are all kinds of filters, including Gaussian blur and different types of lighting. Plus, they can be referenced in a CSS filter and applied to any element in addition to SVG.

What else can you think of? Please let us know what you discover in the comments.

Browser support

We can’t escape talking about browser support here. The core of this technique is supported by all modern browsers. As you might expect, it does not work in Internet Explorer. That said, Internet Explorer does support SVG as a background in CSS (just not with the actual CSS filter property).

SVG as a CSS background image

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
5249165

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
10810734.2-4.3

CSS filter effects

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
18*35No796*

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1081074.4*6.0-6.1*

I’ve also noticed that Blink-based browsers (e.g. Chrome) and WebKit-based one (e.g. Safari) implement mix-blend-mode slightly differently, so please be sure to test across browsers if using CSS blending. In my own projects, I’ve used browser-specific media queries to manually reconcile the visual differences with small tweaks to CSS.


That’s it! Now that you have a grasp of SVG filters and how to combine them with CSS filters as a background, you have yet another neat visual effect to add depth and texture to a design.


Grainy Gradients originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/grainy-gradients/feed/ 9 351302
Creating Colorful, Smart Shadows https://css-tricks.com/creating-colorful-smart-shadows/ https://css-tricks.com/creating-colorful-smart-shadows/#comments Tue, 04 May 2021 14:19:48 +0000 https://css-tricks.com/?p=339742 A bona fide CSS trick from Kirupa Chinnathambi here. To match a colored shadow with the colors in the background-image of an element, you inherit the background in a pseudo-element, kick it behind the original, then blur and filter it. …


Creating Colorful, Smart Shadows originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
A bona fide CSS trick from Kirupa Chinnathambi here. To match a colored shadow with the colors in the background-image of an element, you inherit the background in a pseudo-element, kick it behind the original, then blur and filter it.

.colorfulShadow {
  position: relative;
}

.colorfulShadow::after {
  content: "";
  width: 100%;
  height: 100%;
  position: absolute;
  background: inherit;
  background-position: center center;
  filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
  z-index: -1;
}

Negative z-index is always a yellow flag for me as that only works if there are no intermediary backgrounds. But the trick holds. There would always be some other way to layer the backgrounds (like a <span> or whatever).

For some reason this made me think of a demo I saw (I can’t remember who to credit!). Emojis had text-shadow on them, which really made them pop. And those shadows could also be colorized to a similar effect.

To Shared LinkPermalink on CSS-Tricks


Creating Colorful, Smart Shadows originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/creating-colorful-smart-shadows/feed/ 1 339742
Platform News: Prefers Contrast, MathML, :is(), and CSS Background Initial Values https://css-tricks.com/platform-news-prefers-contrast-mathml-is-and-css-background-initial-values/ https://css-tricks.com/platform-news-prefers-contrast-mathml-is-and-css-background-initial-values/#comments Fri, 19 Mar 2021 15:05:14 +0000 https://css-tricks.com/?p=336679 In this week’s round-up, prefers-contrast lands in Safari, MathML gets some attention, :is() is actually quite forgiving, more ADA-related lawsuits, inconsistent initial values for CSS Backgrounds properties can lead to unwanted — but sorta neat — patterns.

The prefers-contrast: more


Platform News: Prefers Contrast, MathML, :is(), and CSS Background Initial Values originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
In this week’s round-up, prefers-contrast lands in Safari, MathML gets some attention, :is() is actually quite forgiving, more ADA-related lawsuits, inconsistent initial values for CSS Backgrounds properties can lead to unwanted — but sorta neat — patterns.

The prefers-contrast: more media query is supported in Safari Preview

After prefers-reduced-motion in 2017, prefers-color-scheme in 2019, and forced-colors in 2020, a fourth user preference media feature is making its way to browsers. The CSS prefers-contrast: more media query is now supported in the preview version of Safari. This feature will allow websites to honor a user’s preference for increased contrast.

Screenshot of the iPhone 12 landing page on Apple's website. A big red arrow points out light grey text on the page.
Apple could use this new media query to increase the contrast of gray text on its website
.pricing-info {
  color: #86868b; /* contrast ratio 3.5:1 */
}

@media (prefers-contrast: more) {
  .pricing-info {
    color: #535283; /* contrast ratio 7:1 */
  }
}

Making math a first-class citizen on the web

One of the earliest specifications developed by the W3C in the mid-to-late ’90s was a markup language for displaying mathematical notations on the web called MathML. This language is currently supported in Firefox and Safari. Chrome’s implementation was removed in 2013 because of “concerns involving security, performance, and low usage on the Internet.”

If you’re using Chrome or Edge, enable “Experimental Web Platform features” on the about:flags page to view the demo.

There is a renewed effort to properly integrate MathML into the web platform and bring it to all browsers in an interoperable way. Igalia has been developing a MathML implementation for Chromium since 2019. The new MathML Core Level 1 specification is a fundamental subset of MathML 3 (2014) that is “most suited for browser implementation.” If approved by the W3C, a new Math Working Group will work on improving the accessibility and searchability of MathML.

The mission of the Math Working Group is to promote the inclusion of mathematics on the Web so that it is a first-class citizen of the web that displays well, is accessible, and is searchable.

CSS :is() upgrades selector lists to become forgiving

The new CSS :is() and :where() pseudo-classes are now supported in Chrome, Safari, and Firefox. In addition to their standard use cases (reducing repetition and keeping specificity low), these pseudo-classes can also be used to make selector lists “forgiving.”

For legacy reasons, the general behavior of a selector list is that if any selector in the list fails to parse […] the entire selector list becomes invalid. This can make it hard to write CSS that uses new selectors and still works correctly in older user agents.

In other words, “if any part of a selector is invalid, it invalidates the whole selector.” However, wrapping the selector list in :is() makes it forgiving: Unsupported selectors are simply ignored, but the remaining selectors will still match.

Unfortunately, pseudo-elements do not work inside :is() (although that may change in the future), so it is currently not possible to turn two vendor-prefixed pseudo-elements into a forgiving selector list to avoid repeating styles.

/* One unsupported selector invalidates the entire list */
::-webkit-slider-runnable-track, ::-moz-range-track {
  background: red;
}

/* Pseudo-elements do not work inside :is() */
:is(::-webkit-slider-runnable-track, ::-moz-range-track) {
  background: red;
}

/* Thus, the styles must unfortunately be repeated */
::-webkit-slider-runnable-track {
  background: red;
}
::-moz-range-track {
  background: red;
}

Dell and Kraft Heinz sued over inaccessible websites

More and more American businesses are facing lawsuits over accessibility issues on their websites. Most recently, the tech corporation Dell was sued by a visually impaired person who was unable to navigate Dell’s website and online store using the JAWS and VoiceOver screen readers.

The Defendant fails to communicate information about its products and services effectively because screen reader auxiliary aids cannot access important content on the Digital Platform. […] The Digital Platform uses visual cues to convey content and other information. Unfortunately, screen readers cannot interpret these cues and communicate the information they represent to individuals with visual disabilities.

Earlier this year, Kraft Heinz Foods Company was sued for failing to comply with the Web Content Accessibility Guidelines on one of the company’s websites. The complaint alleges that the website did not declare a language (lang attribute) and provide accessible labels for its image links, among other things.

In the United States, the Americans with Disabilities Act (ADA) applies to websites, which means that people can sue retailers if their websites are not accessible. According to the CEO of Deque Systems (the makers of axe), the recent increasing trend of web-based ADA lawsuits can be attributed to a lack of a single overarching regulation that would provide specific compliance requirements.

background-clip and background-origin have different initial values

By default, a CSS background is painted within the element’s border box (background-clip: border-box) but positioned relative to the element’s padding box (background-origin: padding-box). This inconsistency can result in unexpected patterns if the element’s border is semi-transparent or dotted/dashed.

A pink and triple rectangle with rounded edges. The colors overlap in a pattern.
.box {
  /* semi-transparent border */
  border: 20px solid rgba(255, 255, 255, 0.25);

  /* background gradient */
  background: conic-gradient(
    from 45deg at bottom left,
    deeppink,
    rebeccapurple
  );
}

Because of the different initial values, the background gradient in the above image is repeated as a tiled image on all sides under the semi-transparent border. In this case, positioning the background relative to the border box (background-origin: border-box) makes more sense.


Platform News: Prefers Contrast, MathML, :is(), and CSS Background Initial Values originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/platform-news-prefers-contrast-mathml-is-and-css-background-initial-values/feed/ 1 336679
Creative Background Patterns Using Gradients, CSS Shapes, and Even Emojis https://css-tricks.com/creative-background-patterns-using-gradients-css-shapes-and-even-emojis/ https://css-tricks.com/creative-background-patterns-using-gradients-css-shapes-and-even-emojis/#comments Wed, 10 Jun 2020 14:45:25 +0000 https://css-tricks.com/?p=312443 You can create stripes in CSS. That’s all I thought about in terms of CSS background patterns for a long time. There’s nothing wrong with stripes; stripes are cool. They can be customized into wide and narrow bands, criss-crossed …


Creative Background Patterns Using Gradients, CSS Shapes, and Even Emojis originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You can create stripes in CSS. That’s all I thought about in terms of CSS background patterns for a long time. There’s nothing wrong with stripes; stripes are cool. They can be customized into wide and narrow bands, criss-crossed into a checked pattern, and played with in other ways using the idea of hard stops. But stripes can be boring, too. Too conventional, out of fashion, and sometimes even unpleasant.

Thankfully, we can conjure up far more background patterns than you can even imagine with CSS, with code that is similar in spirit to stripes.

Background patterns are images repeated across a background. They can be done by referencing an external image, like a PNG file, or can be drawn with CSS, which is traditionally done using CSS gradients. 

Linear gradients (and repeating linear gradients) for instance, are typically used for stripes. But there are other ways to create cool background patterns. Let’s see how we can use gradients in other ways and toss in other things, like CSS shapes and emoji, to spice things up.

Gradient patterns

There are three types of CSS gradients.

Linear (left), radial (center) and conic (right) gradients
  1. linear-gradient(): Colors flow from left-to-right, top-to-bottom, or at any angle you choose in a single direction.
  2. radial-gradient(): Colors start at a single point and emanate outward
  3. conic-gradient(): Similar in concept to radial gradients, but the color stops are placed around the circle rather than emanating from the center point.

I recommend checking out the syntax for all the gradients to thoroughly understand how to start and end a color in a gradient.

Radial gradient patterns

Let’s look at radial gradients first because they give us very useful things: circles and ellipses. Both can be used for patterns that are very interesting and might unlock some ideas for you!

background: radial-gradient(<gradient values>)

Here’s a pattern of repeating watermelons using this technique:

background: 
	radial-gradient(circle at 25px 9px, black 2px, transparent 2px), 
	radial-gradient(circle at 49px 28px, black 2px, transparent 2px), 
	radial-gradient(circle at 38px 1px, black 2px, transparent 2px), 
	radial-gradient(circle at 20px 4px, black 2px, transparent 2px), 
	radial-gradient(circle at 80px 4px, black 2px, transparent 2px), 
	radial-gradient(circle at 50px 10px, black 2px, transparent 2px), 
	radial-gradient(circle at 60px 16px, black 2px, transparent 2px), 
	radial-gradient(circle at 70px 16px, black 2px, transparent 2px), 
	radial-gradient(ellipse at 50px 0, red 33px, lime 33px, lime 38px, transparent 38px) 
	white;
background-size: 100px 50px;

We start by providing a background size on the element then stack up the gradients inside it. An ellipse forms the green and red parts. Black circles are scattered across to represent the watermelon seeds. 

The first two parameters for a radial gradient function determine whether the gradient shape is a circle or an ellipse and the starting position of the gradient. That’s followed by the gradient color values along with the start and ending positions within the gradient.

Conic gradient patterns

Conic gradients create ray-like shapes. Like linear and radial gradients, conic gradients can be used to create geometric patterns.

background: conic-gradient(<gradient values>)
background: 
  conic-gradient(yellow 40deg, blue 40deg, blue 45deg, transparent 45deg), 
  conic-gradient(transparent 135deg, blue 135deg, blue 140deg, transparent 140deg) ;
background-size: 60px 60px;
background-color: white;

The rub with conic gradient is that it’s not supported in Firefox, at least at the time of writing. It’s always worth keeping an eye out for deeper support.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
6983No7912.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
10810710812.2-12.5

Emoji icon patterns

This is where things begin to get interesting. Rather than just using geometric patterns (as in gradients), we now use the organic shapes of emojis to create background patterns. 🎉 

It starts with emoji icons. 

Solid-color emoji patterns

We can create emoji icons by giving emojis a transparent color and text shadow.

color: transparent;
text-shadow: 0 0 black;

Those icons can then be turned into an image that can be used as a background, using SVG.

<svg>
  <foreignObject>
    <!-- The HTML code with emoji -->
  </foreignObject>
</svg>

The SVG can then be referred by the background property using data URL

background: url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><!-- SVG code --></svg>");

And, voilá! We get something like this:

background: 
    url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><foreignObject width=%22100px%22 height=%22100px%22><div xmlns=%22http://www.w3.org/1999/xhtml%22 style=%22color:transparent;text-shadow: 0 0 %23e42100, -2px 2px 0 black;font-size:70px%22>🏄‍♀️</div></foreignObject></svg>"), 
    white; 
background-size: 60px 60px; 

Other than emojis, it’s also possible to draw CSS shapes and use them as patterns. Emojis are less work, though. Just saying. 

Gradient-colored emoji patterns

Instead of using plain emoji icons, we can use gradient emoji icons. To do that, skip the text shadow on the emojis. Add a gradient background behind them and use background-clip to trim the gradient background to the shape of the emojis. 

color: transparent;
background: linear-gradient(45deg, blue 20%, fuchsia);
background-clip: text; /* Safari requires -webkit prefix */

Then, just as before, use the combination of SVG and data URL to create the background pattern.

Translucent-colored emoji patterns

This is same as using block colored emoji icons. This time, however, we take away the opaqueness of the colors by using rgba() or hsla() values for the text shadow. 

color: transparent;
text-shadow: 20px 10px rgba(0, 255, 0, .3), 
             0 0 red;

SVG-text emoji patterns

We’ve already looked at all the working methods I could think of to create background patterns, but I feel like I should also mention this other technique I tried, which is not as widely supported as I’d hoped.

 I tried placing the emoji in an SVG <text> element instead of the HTML added using <foreignObject>. But I wasn’t able to create a solid shadow behind it in all the browsers.

background: 
  url("data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%221em%22 font-size=%2270%22 fill=%22transparent%22 style=%22text-shadow: 0 0 %23e42100, -2px 2px 5px black, 0 0 6px white; ;%22>🏄‍♀️</text></svg>")

Just in case, I tried using CSS and SVG filters for the shadow as well, thinking that might work. It didn’t. I also tried using the stroke attribute, to at least create an outline for the emoji, but that didn’t work, either. 

CSS element() patterns

I didn’t think of SVG when I first thought of converting emoji icons or CSS shapes into background images. I tried CSS element(). It’s a function that directly converts an HTML element into an image that can be referenced and used. I really like this approach, but browser support is a huge caveat, which is why I’m mentioning it here at the end.

Basically, we can drop an element in the HTML like this:

<div id=snake >🐍</div>

…then pass it into the element() function to use like an image on other elements, like this:

background: 
  -moz-element(#snake), /* Firefox only */
  linear-gradient(45deg, transparent 20px, blue 20px, blue 30px, transparent 30px) 
  white;
background-size: 60px 60px;
background-color: white;

Now that snake emoji is technically an image that we get to include in the pattern.

Again, browser support is spotty, making this approach super experimental.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
No4*NoNoNo

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
No107*NoNo

In this method, the original emoji (or any CSS shape for that matter) used for the background pattern needs to render on screen for it to appear in the background pattern as well. To hide that original emoji, I used mix-blend-mode — it sort of masks out the original emoji in the HTML so it doesn’t show up on the page.


I hope you find the methods in this post useful in one way or another and learned something new in the process! Give them a try. Experiment with different emojis and CSS shapes because gradients, while cool and all, aren’t the only way to make patterns.. The background property takes multiple values, allowing us to think of creative ways to stack things.


Creative Background Patterns Using Gradients, CSS Shapes, and Even Emojis originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/creative-background-patterns-using-gradients-css-shapes-and-even-emojis/feed/ 1 312443
Managing Multiple Backgrounds with Custom Properties https://css-tricks.com/managing-multiple-backgrounds-with-custom-properties/ https://css-tricks.com/managing-multiple-backgrounds-with-custom-properties/#comments Mon, 15 Jul 2019 21:17:20 +0000 http://css-tricks.com/?p=288712 One cool thing about CSS custom properties is that they can be a part of a value. Let’s say you’re using multiple backgrounds to pull off a design. Each background will have its own color, image, repeat, position, etc. It …


Managing Multiple Backgrounds with Custom Properties originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
One cool thing about CSS custom properties is that they can be a part of a value. Let’s say you’re using multiple backgrounds to pull off a design. Each background will have its own color, image, repeat, position, etc. It can be verbose!

You have four images:

body {
  
  background-position:
    top 10px left 10px,
    top 10px right 10px,
    bottom 10px right 10px,
    bottom 10px left 10px;
  
  background-repeat: no-repeat;
  
  background-image:
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg),
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg),
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg),
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);
  
}

You want to add a fifth in a media query:

@media (min-width: 1500px) {
  body {
    /* REPEAT all existing backgrounds, then add a fifth. */
  }
}

That’s going to be super verbose! You’ll have to repeat each of those four images again, then add the fifth. Lots of duplication there.

One possibility is to create a variable for the base set, then add the fifth much more cleanly:

body {
  --baseBackgrounds: 
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg),
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg),
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg),
    url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);

  background-position:
    top 10px left 10px,
    top 10px right 10px,
    bottom 10px right 10px,
    bottom 10px left 10px;
  
  background-repeat: no-repeat;
  
  background-image: var(--baseBackgrounds);
}
@media (min-width: 1500px) {
  body {
    background-image: 
      var(--baseBackgrounds),
      url(added-fifth-background.svg);
  }
}

But, it’s really up to you. It might make more sense and be easier manage if you made each background image into a variable, and then pieced them together as needed.

body {
  --bg1: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg);
  --bg2: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg);
  --bg3: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg);
  --bg4: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);
  --bg5: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);
  
  background-image: var(--bg1), var(--bg2), var(--bg3), var(--bg4);
}
@media (min-width: 1500px) {
  body {
    background-image: var(--bg1), var(--bg2), var(--bg3), var(--bg4), var(--bg5);
  }
}

Here’s a basic version of that, including a supports query:

See the Pen
Multiple BGs with Custom Properties
by Chris Coyier (@chriscoyier)
on CodePen.

Dynamically changing just the part of a value is a huge strength of CSS custom properties!

Note, too, that with backgrounds, it might be best to include the entire shorthand as the variable. That way, it’s much easier to piece everything together at once, rather than needing something like…

--bg_1_url: url();
--bg_1_size: 100px;
--bg_1_repeat: no-repeat;
/* etc. */

It’s easier to put all of the properties into shorthand and use as needed:

body {  
  --bg_1: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg) top 10px left 10px / 86px no-repeat;
  --bg_2: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg) top 10px right 10px / 86px no-repeat;
  --bg_3: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg) bottom 10px right 10px / 86px no-repeat;
  --bg_4: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg) bottom 10px left 10px  / 86px no-repeat;
    
  background:
    var(--bg_1), var(--bg_2),var(--bg_3),var(--bg_4);
}

Like this.


Managing Multiple Backgrounds with Custom Properties originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/managing-multiple-backgrounds-with-custom-properties/feed/ 7 288712
Multiple Background Clip https://css-tricks.com/multiple-background-clip/ Wed, 30 Jan 2019 22:39:16 +0000 http://css-tricks.com/?p=282018 You know how you can have multiple backgrounds?

body {
  background-image: 
    url(image-one.jpg),
    url(image-two.jpg);
}

That’s just background-image. You can set their position too, as you might expect. We’ll shorthand it:

body {
  background: 
    url(image-one.jpg) no-repeat top right,
    url(image-two.jpg) 


Multiple Background Clip originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You know how you can have multiple backgrounds?

body {
  background-image: 
    url(image-one.jpg),
    url(image-two.jpg);
}

That’s just background-image. You can set their position too, as you might expect. We’ll shorthand it:

body {
  background: 
    url(image-one.jpg) no-repeat top right,
    url(image-two.jpg) no-repeat bottom left;
}

I snuck background-repeat in there just for fun. Another one you might not think of setting for multiple different backgrounds, though, is background-clip. In this linked article, Stefan Judis notes that this unlocks some pretty legit CSS-Trickery!

To Shared LinkPermalink on CSS-Tricks


Multiple Background Clip originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
282018
Moving Backgrounds With Mouse Position https://css-tricks.com/moving-backgrounds-with-mouse-position/ https://css-tricks.com/moving-backgrounds-with-mouse-position/#comments Thu, 04 Oct 2018 14:04:25 +0000 http://css-tricks.com/?p=276364 Let’s say you wanted to move the background-position on an element as you mouse over it to give the design a little pizzazz. You have an element like this:

<div class="module" id="module"></div>

And you toss a background on it:

.module 


Moving Backgrounds With Mouse Position originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Let’s say you wanted to move the background-position on an element as you mouse over it to give the design a little pizzazz. You have an element like this:

<div class="module" id="module"></div>

And you toss a background on it:

.module {
  background-image: url(big-image.jpg);
}

You can adjust the background-position in JavaScript like this:

const el = document.querySelector("#module");

el.addEventListener("mousemove", (e) => {
  el.style.backgroundPositionX = -e.offsetX + "px";
  el.style.backgroundPositionY = -e.offsetY + "px";
});

See the Pen Move a background with mouse by Chris Coyier (@chriscoyier) on CodePen.

Or, you could update CSS custom properties in the JavaScript instead:

const el = document.querySelector("#module");

el.addEventListener("mousemove", (e) => {
  el.style.setProperty('--x', -e.offsetX + "px");
  el.style.setProperty('--y', -e.offsetY + "px");
});
.module {
  --x: 0px;
  --y: 0px;
  background-image: url(large-image.jpg);
  background-position: var(--x) var(--y);
}

See the Pen Move a background with mouse by Chris Coyier (@chriscoyier) on CodePen.

Here’s an example that moves the background directly in JavaScript, but with a transition applied so it slides to the new position rather than jerking around the first time you enter:

See the Pen Movable Background Ad by Chris Coyier (@chriscoyier) on CodePen.

Or, you could move an actual element instead (rather than the background-position). You’d do this if there is some kind of content or interactivity on the sliding element. Here’s an example of that, which sets CSS custom properties again, but then actually moves the element via a CSS translate() and a calc() to temper the speed.

See the Pen Hotjar Moving Heatmap Ad by Chris Coyier (@chriscoyier) on CodePen.

I’m sure there are loads of other ways to do this — a moving SVG viewBox, scripts controlling a canvas, webGL… who knows! If you have some fancier ways to handle this, link ’em up in the comments.


Moving Backgrounds With Mouse Position originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/moving-backgrounds-with-mouse-position/feed/ 9 276364
CSS Basics: Using Multiple Backgrounds https://css-tricks.com/css-basics-using-multiple-backgrounds/ https://css-tricks.com/css-basics-using-multiple-backgrounds/#comments Wed, 14 Feb 2018 20:53:41 +0000 http://css-tricks.com/?p=266396 With CSS, you can control the background of elements. You can set a background-color to fill it with a solid color, a background-image to fill it with (you guessed it) an image, or even both:

body {
  background-color: red;
  background-image: 


CSS Basics: Using Multiple Backgrounds originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
With CSS, you can control the background of elements. You can set a background-color to fill it with a solid color, a background-image to fill it with (you guessed it) an image, or even both:

body {
  background-color: red;
  background-image: url(pattern.png);
}

Here’s an example where I’m using an SVG image file as the background, embedded right in the CSS as a data URL.

See the Pen background color and image together by Chris Coyier (@chriscoyier) on CodePen.

That’s just a single image there, repeated, but we can actually set multiple background images if we want. We do that by separating the values with commas.

body {
  background-image: 
    url(image-one.jpg),
    url(image-two.jpg);
}

If we leave it like that, image-one.jpg will repeat and entirely cover image-two.jpg. But we can control them individually as well, with other background properties.

body {
  background-image: 
    url(image-one.jpg),
    url(image-two.jpg);
  background-position:
    top right, /* this positions the first image */
    bottom left; /* this positions the second image */
  background-repeat:
    no-repeat; /* this applies to both images */
}

See how background-position also has comma-separated values? Those will apply individually to each image respectively. And then how background-repeat has only one value? We could have done two values in the same way, but by using just one value, it applies to both.

Here’s an example using four separate images, one in each corner, offset by a smidge:

See the Pen Example of multiple backgrounds by Chris Coyier (@chriscoyier) on CodePen.

It’s too bad you can’t rotate or flip background images or else we could have used just one. We can rotate and flip entire elements (or pseudo elements) though, so in cases like that, we can get away with using a single image!

See the Pen Flipping Image So You Can Use Just One by Chris Coyier (@chriscoyier) on CodePen.

Just a few other things to be aware of here:

  1. The stacking order of multiple background is “first is on top.”
  2. Gradients are applied through background-image, so they can be used as part of all this. For example, you could set a transparent gradient over a raster image.

See the Pen Tinted Image w/ Multiple Backgrounds by Chris Coyier (@chriscoyier) on CodePen.


CSS Basics: Using Multiple Backgrounds originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/css-basics-using-multiple-backgrounds/feed/ 13 266396
Methods for Contrasting Text Against Backgrounds https://css-tricks.com/methods-contrasting-text-backgrounds/ https://css-tricks.com/methods-contrasting-text-backgrounds/#comments Tue, 09 May 2017 12:00:54 +0000 http://css-tricks.com/?p=254378 It started with seeing a recent Pen of Mandy Michael’s text effects demos. I’m a very visual creature, so the first thing I noticed was the effect, not the title (which clearly states how the effect was achieved). Instantly, …


Methods for Contrasting Text Against Backgrounds originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
It started with seeing a recent Pen of Mandy Michael’s text effects demos. I’m a very visual creature, so the first thing I noticed was the effect, not the title (which clearly states how the effect was achieved). Instantly, my mind went “blend modes!”, which turned out to be wrong.

The demo actually uses clip-path. First of all, the text is duplicated. We have black text below as the actual text content of the element and the white text above as the value of the content property (taken from a data attribute which gets updated via JS). These two are stacked one on top of each other (they completely overlap). Then the pseudo-element with the white text above gets clipped to the shape of the black dress.

However, this means we need to change the clipping path if we change the image and, at this point, it’s anything but easy to figure out polygonal clipping paths with a lot of points via dev tools (which is why having something like Benett Feely’s Clippy with two-way editing directly in dev tools would be immensely useful). So I decided to give my initial idea – blend modes – a try.

Let’s say we have a heading in a contentEditable1 container with a black and white image (well, grayscale) background. The HTML structure is as follows:

<header>
  <h2 contentEditable role='textbox' aria-multiline='true'>And stay alive</h2>
</header>

We set the background-image on the header container, we give the h2 white text and set its mix-blend-mode to difference or exclusion. The relevant CSS is below:

header { background: url(black-and-white-image.jpg) }

h2 {
  color: white;
  mix-blend-mode: difference;
}

I can’t really understand blend modes or normally see a difference between difference and exclusion, but according to MDN, they’re pretty much the same, with exclusion having less contrast. What I can understand in this situation is that having white text over the image gives us a result that’s the image inverted where the text overlaps it. For simple black and white images, black in the original image becomes white where we have white text above it and white in the original image becomes black where we have white text above it.

The result can be seen in the following Pen:

See the Pen by thebabydino (@thebabydino) on CodePen.

Mission accomplished! Both the text and the image can be changed and the effect is preserved without the need for any JavaScript or for any changes to the CSS.

But I instantly found that there was another itch to scratch: what happens if the image isn’t just black and white? Well, let’s try that! Turns out the result actually looks pretty good:

See the Pen by thebabydino (@thebabydino) on CodePen.

However, the text isn’t grayscale anymore and setting filter: grayscale(1) doesn’t change anything. Does any filter value work? Well, tried drop-shadow() next to try to find an answer to this question. And the answer is that, yes, drop-shadow() works, but the way it works – the shadow being blended with the header background2 – provides a clue about why grayscale() didn’t change a thing: filters are applied before blending, our text is white and the output of grayscale() in this case is identical to its input (white in, white out). And, since nothing changes before the blending, its result is the same.

See the Pen by thebabydino (@thebabydino) on CodePen.

This probably shouldn’t have been a surprise. I’ve ran into issues caused by the order in which properties are applied before.

For example, filter is also applied before clip-path, so if we clip an element to a non-rectangular shape and we want to have a drop shadow on it, tough luck, setting the filter on the same element doesn’t give the expected result. This is because the rectangular element gets the filter applied, so we have a drop shadow around its rectangular box and only after that gets clipped to the shape specified via clip-path. This is always the order these two get applied in, regardless of the order you set them in the CSS.

Diagram. A box representing an element (left) 
has a CSS filter applied to become a box with a box-shadow (center) then has a clip-path applied to 
become a star with no shadow (right).
Diagram of how browsers apply filter and clip-path when they’re set on the same element.

The way to solve the filter + clip-path problem is to set the filter on a parent element with nothing visible except the clipped child. The “nothing visible” part is important because, if the parent has some visible text or borders, they’ll get the drop shadow as well, while if it has a background, then the whole background area gets the shadow.

See the Pen by thebabydino (@thebabydino) on CodePen.

However, this solution doesn’t work for the filter + mix-blend-mode problem as well. Wrapping our h2 into a div and setting filter on that div breaks the blending effect.

See the Pen by thebabydino (@thebabydino) on CodePen.

What’s worse is that I can’t seem to think of anything I could do to get around this problem. There might be a way of doing it by duplicating the text and using a luminosity blend mode, but, as mentioned before, I don’t really understand blend modes and I haven’t been able to get that right.

But maybe we could try a different approach altogether, one that doesn’t use blending. All the playing with filters gave me the idea that we could apply the image to the text, then apply an invert() filter, to which we could chain grayscale(), contrast() and more.

With this method using background-clip: text, we also have the advantage of a cross-browser solution, since Firefox and Edge have now implemented this too.

The way we go about this is the following: we make sure the header and the h2 have identical backgrounds and that these backgrounds perfectly overlap. Then we set color: transparent on the h2 and clip its background to text. The final step is to set filter: invert(1) on the h2. The relevant CSS3 is as follows:

h2 {
  background: inherit;
  background-clip: text;
  color: transparent;
  filter: invert(1);
}

The result can be seen in the following Pen:

See the Pen by thebabydino (@thebabydino) on CodePen.

It looks like before, except it’s using a different method and now we can chain more functions to the filter property. For example, we can make the text grayscale and up its contrast:

filter: invert(1) grayscale(1) contrast(9)

See the Pen by thebabydino (@thebabydino) on CodePen.

Tweaking the filter value is also how we add a text shadow. While in the first case (using mix-blend-mode) we can simply set the text-shadow property (and the shadow also gets blended with the background), doing so in the second case breaks things:

See the Pen by thebabydino (@thebabydino) on CodePen.

Fortunately, we can chain drop-shadow() to our filter.

See the Pen by thebabydino (@thebabydino) on CodePen.

The Pen below shows the two methods described in this article. On the left, we have the mix-blend-mode method and on the right, we have the background-clip and filter method (with the extra grayscale and contrast components). The text is editable and the thumbnails allow for changing the background-image:

See the Pen by thebabydino (@thebabydino) on CodePen.

So, if we pit these methods against each other, which is better?

When don’t go into aesthetics because it’s a subjective matter and it probably differs from case to case and even from mood to mood.

As far as basic support is concerned, the last method gets an advantage since it’s supported in Edge, while mix-blend-mode isn’t (but if you want it in Edge, please vote for it because your feedback does matter). Mandy’s original example uses clip-path, another very useful feature, which sadly doesn’t work in Edge either (you can vote for it here).

When it comes to selecting text, the mix-blend-mode method works perfectly and looks the best across the browsers it’s supported.

The editable text, made to contrast with the background image using the mix-blend-mode method, shown selected in its entirety. The selection background is blended with the image underneath.
Selecting text when using the mix-blend-mode method

Using the clip-path method, the selection looks clean and the text remains readable, but it seemed to stumble in Firefox while I was over the pseudo-element text. Fortunately, this problem turned out to have an easy fix: setting pointer-events: none on the pseudo-element.

Animated gif. The editable text, made to contrast with the background image using the clip-path method, gets selected in Firefox. The selection stumbles where the copy of this text, generated via a pseudo-element, overlaps the original. Setting pointer-events: none on the pseudo-element fixes this problem.
Selecting text in Firefox when using the clip-path method

As for the last method, the selection can look ugly and can make the text harder to read. Not to mention that the drop shadow ends up being applied to the whole selection rectangle in this case, not just to the actual text.

The editable text, made to contrast with the background image using the background-clip: text + filter method, shown selected in its entirety. The whole selection box has the filter effect applied, not just the text, so the selection background is grayscale and the drop-shadow is now on the selection box, not just on the text itself.
Selecting text when using the background-clip: text + filter method

Changing the text also gets awkward in Firefox with the last method, the screen getting “dirty” as I type new text.

Animated gif. The editable text, made to contrast with the background image using the background-clip: text + filter method, gets edited in Firefox. As you write, the text becomes clipped and garbled, overlapping itself.
Changing text in Firefox when using the background-clip: text + filter method

The clip-path method also had a problem with changing text in Firefox at first: trying to start editing from the middle of the pseudo-element text didn’t work. Fortunately, setting pointer-events: none on the pseudo-element fixes this as well.

Animated gif. The editable text, made to contrast with the background image using the clip-path method, gets edited in Firefox. The cursor cannot be placed to start editing from the part where the copy of this text, generated via a pseudo-element, overlaps the original. Setting pointer-events: none on the pseudo-element fixes this problem.
Changing text in Firefox when using the clip-path method

As far as flexibility in terms of how we can alter the text goes, the last method fares best because chaining filter functions can take us a long way.

At the end of the day, which is better ends up depending on the particular use case. What browsers should be supported? Does the image change? Does the text change? How should the text be visually altered?


1 contentEditable isn’t accessible in all browsers by default, so we need to provide semantics to fix that.

2 When experimenting with blend modes, be aware of the legibility issues they can produce, particularly regarding contrast. WCAG 2.0 states that, unless the text forms part of purely decorative imagery, it should pass a minimum contrast threshold. Tools like Color ContrastAnalyzer can help you meet that requirement.

3 Prefixes are omitted for brevity, but background-clip still needs the -webkit- prefix for WebKit browsers (Firefox and Edge have implemented it unprefixed, though they both support it with the -webkit- prefix as well, probably because it has already been used to death only with that prefix) and this prefix needs to be added manually/ via a preprocessor mixin, which is something that I normally don’t encourage, but, in this particular case, auto-prefixing via Autoprefixer or Prefixfree doesn’t happen (Prefixfree works via feature detection, which doesn’t catch properties such as background-clip, filter or clip-path and this is the Autoprefixer issue). As for filter, it’s now supported unprefixed in all current desktop browsers and Autoprefixer can prefix it anyway.


Methods for Contrasting Text Against Backgrounds originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/methods-contrasting-text-backgrounds/feed/ 16 254378
Hero Patterns https://css-tricks.com/hero-patterns/ Wed, 25 Jan 2017 12:25:22 +0000 http://css-tricks.com/?p=250451 A project by Steve Schoger:

A collection of repeatable SVG background patterns for you to use on your digital projects.

Customizeable patterns. You can even snag the path data for your own deeds.

To Shared LinkPermalink on CSS-Tricks


Hero Patterns originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
A project by Steve Schoger:

A collection of repeatable SVG background patterns for you to use on your digital projects.

Customizeable patterns. You can even snag the path data for your own deeds.

To Shared LinkPermalink on CSS-Tricks


Hero Patterns originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
250451
background-position https://css-tricks.com/almanac/properties/b/background-position/ https://css-tricks.com/almanac/properties/b/background-position/#comments Tue, 17 Feb 2015 21:32:02 +0000 http://css-tricks.com/?page_id=196146 The background-position property in CSS allows you to move a background image (or gradient) around within its container.

html {
  background-position: 100px 5px; 
}

It has three different types of values:

  • Length values (e.g. 100px 5px)
  • Percentages (e.g. 100%


background-position originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The background-position property in CSS allows you to move a background image (or gradient) around within its container.

html {
  background-position: 100px 5px; 
}

It has three different types of values:

  • Length values (e.g. 100px 5px)
  • Percentages (e.g. 100% 5%)
  • Keywords (e.g. top right)

The default values are 0 0. This places your background image at the top-left of the container.

Length values are pretty simple: the first value is the horizontal position, second value is the vertical position. So 100px 5px will move the image 100px to the right and five pixels down. You can set length values in px, em, or any of the other CSS length values.

Percentages work a little differently. Get your math hats out: moving a background image by X% means it will align the X% point in the image to the X% point in the container. For example, 50% means it will align the middle of the image with the middle of the container. 100% means it will align the last pixel of the image with the last pixel of the container, and so on.

Keywords are just shortcuts for percentages. It’s easier to remember and write top right than 0 100%, and that’s why keywords are a thing. Here is a list of all five keywords and their equivalent values:

  • top: 0% vertically
  • right: 100% horizontally
  • bottom: 100% vertically
  • left: 0% horizontally
  • center: 50% horizontally if horizontal isn’t already defined. If it is then this is applied vertically.

It’s interesting to note that it doesn’t matter what order you use for the keywords: top center is the same as center top. You can only do this if you’re exclusively using keywords, though. center 10% is not the same as 10% center.

Demo

This demo shows examples of background-position set with length units, percentages, and keywords.

Declaring values

You can give background-position up to four values in modern browsers:

  • If you declare one value, that value is the horizontal offset. The browser sets the vertical offset to center.
  • When you declare two values, the first value is the horizontal offset and the second value is the vertical offset.

Things get a little trickier when you start using three or four values, but you also get more control over your background placement. A three- or four-value syntax alternates between keywords and length or percentage units. You can use any of the keyword values except center in a three- or four-value background-position declaration.

When you specify three values, the browser interpets the “missing” fourth value as 0. Here’s an example of a three-value background-position:

.three-values {
  background-position: right 45px bottom;
}

This positions the background image 45px from the right and 0px from the bottom of the container.

Here’s an example of a four-value background-position:

.four-values {
  background-position: right 45px bottom 20px;
}

This puts the background image 45px from the right and 20px from the bottom of the container.

Notice the order of the values in the examples above: keywords followed by length units. A three- or four-value background-position must follow that format, with a keyword preceding a length or percentage unit.

Demo

This demo includes examples of one value, two value, three value, and four value background-position.

Browser support

The basic values are supported everywhere. The four-value syntax has this support:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
25139127

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1081074.47.0-7.1

That’s the same level of support as the background-position-x and background-position-y properties.

More information


background-position originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/almanac/properties/b/background-position/feed/ 13 196146
background https://css-tricks.com/almanac/properties/b/background/ https://css-tricks.com/almanac/properties/b/background/#comments Thu, 01 Sep 2011 03:00:46 +0000 http://css-tricks.com/?page_id=13963 The background property in CSS allows you to control the background of any element (what paints underneath the content in that element). It is a shorthand property, which means that it allows you to write what would be multiple CSS …


background originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The background property in CSS allows you to control the background of any element (what paints underneath the content in that element). It is a shorthand property, which means that it allows you to write what would be multiple CSS properties in one. Like this:

body {
  background:
     url(sweettexture.jpg)    /* image */
     top center / 200px 200px /* position / size */
     no-repeat                /* repeat */
     fixed                    /* attachment */
     padding-box              /* origin */
     content-box              /* clip */
     red;                     /* color */
}

background is made up of eight other properties:

You can use any combination of these properties that you like, in almost any order (although the order recommended in the spec is above). There is a gotcha though: anything you don’t specify in the background property is automatically set to its default. So if you do something like this:

body {
  background-color: red;
  background: url(sweettexture.jpg);
}

The background will be transparent, instead of red. The fix is easy though: just define background-color after background, or just use the shorthand (e.g. background: url(...) red;)

Multiple backgrounds

CSS3 added support for multiple backgrounds, which layer over the top of each other. Any property related to backgrounds can take a comma separated list, like this:

body {
  background: url(sweettexture.jpg), url(texture2.jpg) black;
  background-repeat: repeat-x, no-repeat;
}

Each value in the comma separated list corresponds to a layer: the first value is the top layer, the second value is the second layer, and the background color is always the last layer.

Demo

Browser support

Support varies among the different specific properties, and each corresponding article in the Almanac has unique browser support notes. Basic single-color backgrounds and single images work everywhere though, and anything that isn’t supported just falls back to the next best thing, whether that’s an image or a color.

IEEdgeChromeFirefoxSafariOpera
YesYesYesYesYesYes
iOSChrome AndroidFirefox AndroidAndroid BrowserOpera Mobile
YesYesYesYesYes

background originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/almanac/properties/b/background/feed/ 20 13963
Perfect Full Page Background Image https://css-tricks.com/perfect-full-page-background-image/ https://css-tricks.com/perfect-full-page-background-image/#comments Sat, 20 Nov 2010 07:00:45 +0000 http://css-tricks.com/?p=3458 Four techniques are explored on accomplishing a full page background image that conforms to our exceptions: no white space, scales as needed, retains aspect ratio, centered, and more.


Perfect Full Page Background Image originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
This post was originally published on August 21, 2009 and is now updated as it has been entirely revised. Both original methods are removed and now replaced by four new methods.

The goal here is a background image on a website that covers the entire browser window at all times. Let’s put some specifics on it:

  • Fills entire page with image, no white space
  • Scales image as needed
  • Retains image proportions (aspect ratio)
  • Image is centered on page
  • Does not cause scrollbars
  • As cross-browser compatible as possible
  • Isn’t some fancy shenanigans like Flash

Awesome, easy, progressive CSS way

We can do this purely through CSS thanks to the background-size property now in CSS. We’ll use the html element (better than body as it’s always at least the height of the browser window). We set a fixed and centered background on it, then adjust it’s size using background-size set to the cover keyword.

html { 
  background: url(images/bg.jpg) no-repeat center center fixed; 
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
}

Works in:

  • Safari 3+
  • Chrome Whatever+
  • IE 9+
  • Opera 10+ (Opera 9.5 supported background-size but not the keywords)
  • Firefox 3.6+ (Firefox 4 supports non-vendor prefixed version)

Update: Thanks to Goltzman in the comments for pointing out an Adobe Developer Connection article which features some code to make IE do cover backgrounds as well:

filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='.myBackground.jpg', sizingMethod='scale');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='myBackground.jpg', sizingMethod='scale')";

But careful, reader Pierre Orsander said they tried this and had some problems with links on the page going dead.

Update: Matt Litherland writes in to say that anyone trying to use the above IE filters and having problems with scrollbars or dead links or whatever else (like Pierre above) should try not using them on the html or body element. But instead a fixed position div with 100% width and height.

CSS-only technique #1

Big thanks, as usual, to Doug Neiner for this alternate version. Here, we use an inline element, which will be able to resize in any browser. We set a min-height which keeps it filling the browser window vertically, and set a 100% width which keeps it filling horizontally. We also set a min-width of the width of the image so that the image never gets smaller than it actually is.

The especially clever bit is using a media query to check if the browser window is smaller than the image, and using a combo percentage-left and negative left margin to keep it centered regardless.

Here is the CSS:

img.bg {
  /* Set rules to fill background */
  min-height: 100%;
  min-width: 1024px;
	
  /* Set up proportionate scaling */
  width: 100%;
  height: auto;
	
  /* Set up positioning */
  position: fixed;
  top: 0;
  left: 0;
}

@media screen and (max-width: 1024px) { /* Specific to this particular image */
  img.bg {
    left: 50%;
    margin-left: -512px;   /* 50% */
  }
}

Works in:

  • Any version of good browsers: Safari / Chrome / Opera / Firefox
  • IE 6: Borked – but probably fixable if you use some kind of fixed positioning shim
  • IE 7/8: Mostly works, doesn’t center at small sizes but fills screen fine
  • IE 9: Works

View Demo

CSS-only technique #2

One rather simple way to handle this is to put an inline image on the page, fixed position it to the upper-left, and give it a min-width and min-height of 100%, preserving it’s aspect ratio.

<img class="bg" src="images/bg.jpg" alt="">
.bg {
  position: fixed; 
  top: 0; 
  left: 0; 
	
  /* Preserve aspet ratio */
  min-width: 100%;
  min-height: 100%;
}

However, this doesn’t center the image and that’s a pretty common desire here… So, we can fix that by wrapping the image in a div. That div we’ll make twice as big as the browser window. Then the image will be placed, still preserving it’s aspect ratio and covering the visible browser window, and the dead center of that.

<div class="bg">
  <img src="images/bg.jpg" alt="">
</div>
.bg {
  position: fixed; 
  top: -50%; 
  left: -50%; 
  width: 200%; 
  height: 200%;
}
.bg img {
  position: absolute; 
  top: 0; 
  left: 0; 
  right: 0; 
  bottom: 0; 
  margin: auto; 
  min-width: 50%;
  min-height: 50%;
}

Credit to Corey Worrell for the concept on this one.

Works in:

  • Safari / Chrome / Firefox (didn’t test very far back, but recent versions are fine)
  • IE 8+
  • Opera (any version) and IE both fail in the same way (wrongly positioned, not sure why)
  • Peter VanWylen wrote in to say that if you add the image via JavaScript, the img needs to have width: auto; and height: auto; to work in IE 8, 9, or 10.

View Demo

Update January 2018: Trying to get this to work on Android? JL García wrote to me saying he needed to add height: 100%; and overflow: hidden; to the html element to get it to work. The full snippet being:

html {
  background: url(images/bg.jpg) no-repeat center center fixed;
  background-size: cover;
  height: 100%;
  overflow: hidden;
}

I tested it, and it seemed totally correct. Without it / With it.

jQuery method

This whole idea becomes a lot easier (from a CSS perspective) if we know if the aspect ratio of the image (inline we intend to use as a background) is larger or smaller than the current aspect ratio of the browser window. If it is lower, than we can set only the width to 100% on the image and know it will fill both height and width. If it is higher, we can set only the height to 100% and know that it will fill both the height and width.

We have access to this information through JavaScript. As usual around here, I like to lean on jQuery.

<img id="bg" src="images/bg.jpg" alt="">
#bg { position: fixed; top: 0; left: 0; }
.bgwidth { width: 100%; }
.bgheight { height: 100%; }
$(window).load(function() {    
  var theWindow = $(window),
  $bg = $("#bg"),
  aspectRatio = $bg.width() / $bg.height();	    			    		
  function resizeBg() {		
    if ( (theWindow.width() / theWindow.height()) < aspectRatio ) {
      $bg
      .removeClass()
      .addClass('bgheight');
    } else {
      $bg
      .removeClass()
      .addClass('bgwidth');
    }					
  }	                   			
  theWindow.resize(resizeBg).trigger("resize");
});

This doesn’t account for centering, but you could definitely alter this to do that. Credits to Koen Haarbosch for the concept behind this idea.

Works in:

  • IE7+ (could probably get in IE6 with a fixed position shim)
  • Most any other desktop browser

View Demo

Update (June 2012): Reader Craig Manley writes in with a technique to load an appropriately sized background image according to screen. As in, don’t load some huge 1900px wide background image for an iPhone.

First, you’d make images like 1024.jpg, 1280.jpg, 1366.jpg, etc. Then, instead of loading an image, you’d load a shim.

<img id="bg" style="position: fixed; left: 0; top: 0;" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="">

If you don’t like the gif shim (personally I think it’s OK because it’s not “content” it’s a background) you could load up one of the real images instead. This code will account for that.

Then you test the screen width and set the src of the image based on it. The code below does it on resize, which you may or may not want. You could just run the code once if you wanted.

(function() {

var win = $(window);

win.resize(function() {
    
  var win_w = win.width(),
  win_h = win.height(),
  $bg = $("#bg");

    // Load narrowest background image based on 
    // viewport width, but never load anything narrower 
    // that what's already loaded if anything.
    var available = [
      1024, 1280, 1366,
      1400, 1680, 1920,
      2560, 3840, 4860
    ];

    var current = $bg.attr('src').match(/([0-9]+)/) ? RegExp.$1 : null;
    
    if (!current || ((current < win_w) && (current < available[available.length - 1]))) {
      
      var chosen = available[available.length - 1];
      
      for (var i=0; i<available.length; i++)="" {="" if="" (available[i]="">= win_w) {
          chosen = available[i];
          break;
        }
      }
      
      // Set the new image
      $bg.attr('src', '/img/bg/' + chosen + '.jpg');
      
      // for testing...
      // console.log('Chosen background: ' + chosen);
      
    }

    // Determine whether width or height should be 100%
    if ((win_w / win_h) < ($bg.width() / $bg.height())) {
      $bg.css({height: '100%', width: 'auto'});
    } else {
      $bg.css({width: '100%', height: 'auto'});
    }
    
  }).resize();
  
})(jQuery)</available.length;>

Note that screen width isn’t the only possible good information to have when choosing an image size. See this article.

Enjoy

If you use this, please feel free to leave what technique you used and if you altered it in any way in the comments below. Always cool to see techniques “in the wild.”

Just for posterity sake, there is another example in here called table.php which uses an old technique that used to be a part of this article. It had some cleverness, but wasn’t quite as good as either CSS technique now presented above.

Other resources


Perfect Full Page Background Image originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/perfect-full-page-background-image/feed/ 224 3458