Skip to content

Understanding CSS Gradients

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

Color gradients can help improve the design aesthetic of a site. But it's not always so easy to write the CSS to make them work the way you want. There are plenty of tools online for visually building gradients and getting back the CSS to implement them. But those tools won't help as much with debugging or tweaking things at the margin. It's worth having a basic idea of how gradients work so you can manually adjust them yourself.

The most basic linear gradient

A linear gradient smoothly transitions between colors in a single direction. So if you had a box, and you wanted to start with black and transition to white, you could do it like this:

background: linear-gradient(black, white);

Here, you've created a CSS class and set the background of any element with that class to have a linear gradient. This gradient will start with the first color, black, and smoothly interpolate to white.

Linear gradient direction

Right now, the top edge of the element will be black and the bottom edge will be white. If we wanted to make the left edge black and the right edge white, we could add a direction specifying that.

-   background: linear-gradient(black, white);
+   background: linear-gradient(to right, black, white);

Now, we're telling the gradient to go from left to right. You can use directions like to top, to top right, to right, to bottom right, etc. When not specified, the default direction is to bottom.

You can also specify direction more granularly with other units. You can use degrees (deg), gradians (grad), radians (rad), or turns (turn). Our to right example could be rewritten as 90deg, 100grad, 1.5708rad, or 0.25turn.

Linear gradient colors

This gradient is...really boring. It is not at all something we'd want to use. Let's pick some better colors!

-   background: linear-gradient(to right, black, white);
+   background: linear-gradient(to right, red, green, blue);

Ok, this gradient is pretty bad too. But at least it has color!

These colors are called color stops. If you want another color in the gradient, just add another color stop. By default, the color stops are distributed evenly across the gradient. But color stops can also accept a position that specify where along the gradient that color should be.

-   background: linear-gradient(to right, red, green, blue);
+   background: linear-gradient(to right, red, green 40%, blue);

By specifying 40% after green, we've set green to appear 40% along the way through the gradient rather than at the default midpoint. I've used percentages here, but you can also use specific units like pixels.

Color stops with positions can also be used to create striped patterns like so:

-   background: linear-gradient(to right, red, green 40%, blue);
+   background: linear-gradient(to right, red 20%, green 20% 40%, blue 40%);

Here, our first color red is solid from the start until 20% along the gradient. Then, green immediately takes over at 20%, and goes until 40%. Finally, blue takes over at 40%, and continues to the end of the gradient. The first color stop is assumed to begin at 0%, and the last is assumed to end at 100%.

Combining gradients

Using colors with transparency, and background blend modes, you can overlay different gradients to achieve a variety of color effects.

background:
  linear-gradient(to right, rgba(200, 40, 10, 1), rgba(230, 40, 10, 0)),
  linear-gradient(to left, hsl(220, 80%, 45%, 1), hsl(220, 80%, 45%, 0)),
  linear-gradient(0.5turn, rgba(20, 230, 30, 1), rgba(20, 230, 20, 0));
background-blend-mode: difference;

Repeating gradients

Let's say you want to create a repeating striped line pattern. Creating all of the necessary color stops would be impractical. But that's where repeating-linear-gradient comes in! Define the necesary color stops once, and watch it tile across the element.

background: repeating-linear-gradient(
  135deg,
  hsl(180, 60%, 70%) 0 10px, /* a 10px-wide blue stripe */
  hsl(0, 0%, 95%) 10px 20px /* a 10px-wide white stripe */
)

Radial gradients

The humble linear gradient transitions colors along a single direction, like an ocean wave moving toward the shore. But the radial gradient is like a ripple in a pond, moving outward in all directions from a single starting point.

background: radial-gradient(black, white);

Notice the default behavior of this basic radial-gradient. The point from which the transition begins defaults to the center of the element. The shape it makes is not circular, but elliptical; it is expanding and contracting to match the shape of the element. Color stops work the same way that they do with linear gradients.

Radial gradients take an optional shape, size, and position before their color stops.

Circle or ellipse

Radial gradients default to an elliptical shape to stretch and fit the element they are part of. But you can also specify they be circular instead, regardless of element dimensions.

.one {
  background: radial-gradient(ellipse, black, white);
}

.two {
  background: radial-gradient(circle, black, white);
}

Radial gradient position

The default center position is limiting for making really interesting gradients. Thankfully, it's very easy to specify a different position with the at keyword.

/* The default is farthest corner. The shape will intersect at the element's corners which are furthest from the starting point.  */
.one {
  background: radial-gradient(circle at top left, black, white);
}

/* With farthest-side, the shape will intersect with the most distant straight edge of the element. */
.two {
  background: radial-gradient(circle at 100%, black, white);
}

/* Same as farthest-corner, except now it's the closest one. */
.three {
  background: radial-gradient(circle at bottom, black, white);
}

/* Same as the farthest-side, except now it's the closest one. */
.four {
  background: radial-gradient(circle at 30% 70%, black, white);
}

Radial gradient size

There are four ways to size a radial gradient in relation to its element. When a radial gradient is drawn, it creates either a circle or ellipse that intersects the edges of the element in a certain way. The gradient is interpolated from the starting point to that invisible shape intersecting the element edge. The radial gradient's size determines where that shape intersects the edges of the element.

/* The default is farthest corner. The shape will intersect at the element's corners which are furthest from the starting point.  */
.one {
  background: radial-gradient(ellipse farthest-corner at 30%, black, white);
}

/* With farthest-side, the shape will intersect with the most distant straight edge of the element. */
.two {
  background: radial-gradient(ellipse farthest-side at 30%, black, white);
}

/* Same as farthest-corner, except now it's the closest one. */
.three {
  background: radial-gradient(ellipse closest-corner at 30%, black, white);
}

/* Same as the farthest-side, except now it's the closest one. */
.four {
  background: radial-gradient(ellipse closest-side at 30%, black, white);
}

Combining radial gradients

Like we did with linear gradients, we can get creative with radial gradients to create unique and colorful backgrounds! By now, you should understand enough about how gradients work in CSS that you can read the code below, and understand how it's constructing the gradient background you see here.

background:
  repeating-radial-gradient(circle, hsl(190, 80%, 70%, 0.2) 0px 35px, transparent 35px 70px),
  radial-gradient(at top right, hsl(150, 70%, 50%, 1), hsl(200, 80%, 40%, 0)),
  radial-gradient(circle at 0% 50%, hsl(300, 75%, 40%), hsl(200, 90%, 30%, 0)),
  radial-gradient(circle at bottom center, hsl(30, 70%, 70%, 1), hsl(30, 70%, 70%, 0));

Conic gradients

There's one last instance of gradient in CSS to cover: the conic gradient. If the linear gradient moves like an ocean wave, and the radial gradient moves like ripples in a move, the conic gradient moves like the hands on a clock. This one is a bit weird compared to linear and radial, and you may not find much use for it. But it's worth letting you know that it exists.

  background: conic-gradient(black, white);

Where previously color stops used percentages or units to designate position in the gradient, in the conic gradient, you would use angles. All the units you used in linear gradients to designate direction can instead be used in conic gradients for color position.

  border-radius: 50%;
  background: conic-gradient(red 0 120deg, green 120deg 240deg, blue 240deg 0deg);

Conic gradients don't have a repeating version like the others, but you can use other background properties to repeat them. Using such properties can have interesting results. As unlikely as it sounds, you can create a checkerboard pattern with a repeating conic gradient!

  background: conic-gradient(red 0 120deg, green 120deg 240deg, blue 240deg 0deg);

Accessibility

While conic gradients can allow you to create interesting things like pie charts and checkerboards, keep in mind that screen readers do not interpret anything from these styles. If you populated a report with pie charts made from conic gradients, a screen reader would not be able to explain the charts to its user. You probably shouldn't try to use these gradients for anything other than aesthetics.

Conclusion

Hopefully this introduction to CSS gradients will help you feel more comfortable working with the code for them directly, and not feeling beholden to an online generator tool. By all means, feel free to use tools to create complex gradients more quickly than writing them by hand! But now you can have confidence that, when the time comes to make tweaks to them in the code, you'll be able to do so yourself.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

CSS Container Queries, what are they? cover image

CSS Container Queries, what are they?

CSS Container queries, what are they? Intro Media queries have always been crucial to building web applications. They help make our apps more accessible and easier to use and ensure we reach most of our audience. Media queries have been essential in frontend development to create unique user interfaces. But now, there’s something new: Container queries. In this blog post, we’ll explore what Container queries are, how they differ from media queries, and why they’re so amazing. So, let’s get started! Refresh on Media queries Media queries have been available in browsers for a long time, but they didn’t become popular until around 2010 when mobile devices started to take off. Media queries let us add specific styles based on the type of device, like screens or printers. This is especially helpful for creating modern, responsive apps. A simple use of Media queries would be changing, for example, a paragraph's font size when the screen width is less than a specific number. ` In this simple example, when the browser’s viewport width is less or equal to 400px, the font size changes to 8px. Notice how straightforward the syntax is: we start with the keyword @media, followed by the type of device it should apply to. In this case, we use screen so it doesn’t affect users who print the page—if you don’t add anything, then it falls back to the default, which is “all” including both print and screen. Then we specify a media feature, in this case, the width. Container queries Container queries are similar to Media queries. Their main function is to apply styles under certain conditions. The difference is that instead of listening to the viewport of the browser, it listens to a container size. Let’s see this example: In the above layout, we have a layout with a sidebar and three cards as the content. Using Media queries we could listen to the viewport width and change the layout depending on a specific width. Like so: ` That’s acceptable, but it requires us to constantly monitor the layout. For example, if we added another sidebar on the right (really weird, but let’s imagine that this is a typical case), our layout would become more condensed: We would need to change our media queries and adjust their range in this situation. Wouldn’t it be better to check the card container’s width and update its styles based on that? That way, we wouldn’t need to worry about if the layout changes, and that’s precisely what container queries are made for! First, to define the container we are going to listen to, we are going to add a new property to our styles: ` The .container class is the one in which our cards reside. By adding the property `container-type, ' we now define this class as a container we want to listen to. We said inline-size as the value to query based on the inline dimensions of the container because we just want to listen to the element's width. The value of container-type will depend on your use case. If you want to listen to both width and height, then size will be a better fit for you. You can also have normal as your container-type value, which means the element won’t act as a query container at all. This is handy if you need to revert to the default behavior. Next, to define our query, we use the new @container CSS at-rule: ` Notice that it is really similar to how we define our Media queries. Now, if we look at the same screen, we will see the following: This is very powerful because we can now style each component with its own rules without changing the rules based on the layout changes. The @container will affect all the defined containers in the scope; we might not want that. We can define the name of our container to specify that we only want to listen to that in specific: ` We can also have a shorthand to define our container and its name: ` Container query length units Container query lengths are similar to the viewport-percentage length units like vh or vw units, but instead of being relative to the viewport, they are to the dimensions of the query container. We have different units, each relative to different dimensions of the container: - cqw: 1% of a query container's width - cqh: 1% of a query container's height - cqi: 1% of a query container's inline size - cqb: 1% of a query container's block size - cqmin: The smaller value of either cqi or cqb - cqmax: The larger value of either cqi or cqb In our example, we could use them to define the font size of our cards: ` Using these units alone isn’t recommended because they’re percentage-based and can have a value we don’t want. Instead, it’s better to use a dynamic range. Using the max function, we can set 2 values and always pick the highest one. Conclusion Container queries bring a fresh and powerful approach to web design but are not meant to replace Media queries. I think their real power shines when used together. Media queries often require constant adjustments as your layout evolves. Container queries, however, let you style individual components based on their dimensions, making the designs more flexible and easier to manage. Adding a new component or rearranging elements won’t force us to rewrite our media queries. Instead, each component handles its styling, leading to cleaner and more organized code. Please note that, as of writing this blog post, they aren’t compatible with all browsers yet. Take a look at this table from caniuse.com: A good fallback strategy for this, when hitting an unsupported browser would be the use of the @support rule, which allows you to apply styles only if the browser supports the CSS feature. For example: ` Ensure your media queries are good enough to keep everything responsive and user-friendly when the condition is unmet. Thank you for reading! Enjoy the extra flexibility that container queries bring to your web designs. Check out a live demo to see it in action. Happy styling!...

Understanding the Difference Between `:focus` and `:focus-visible` in CSS cover image

Understanding the Difference Between `:focus` and `:focus-visible` in CSS

Understanding the Difference Between :focus and :focus-visible in CSS I have learned my fair share about the importance of keyboard accessibility, so I know that visual indication of the focused element is very important. But the well-known :focus pseudo-class is not always the best fit for this job. That's where :focus-visible comes in. Let's look at the differences between these two pseudo-classes and explore the best practices for using them effectively. What is the :focus Pseudo-Class? The :focus pseudo-class is a CSS selector that applies styles to any element that receives focus, regardless of how that focus was triggered. This includes focus events from keyboard navigation, mouse clicks, and touch interactions. Example Usage of :focus ` In this example, the button will display a blue outline whenever it is focused, whether the user clicks on it with a mouse, taps it on a touchscreen, or navigates to it using the keyboard. What is the :focus-visible Pseudo-Class? The :focus-visible pseudo-class is more specialized. It only applies styles to an element when the browser determines that the focus should be visible. This typically occurs when the user navigates via the keyboard or assistive technologies rather than through mouse or touch input. Example Usage of :focus-visible ` Here, the button will only show a blue outline when focused through keyboard navigation or another input method that usually requires visible focus indicators. Key Differences Between :focus and :focus-visible :focus - Behavior: Applies to any element that receives focus, regardless of the input method. - Use Cases: Ensures that all interactions with the element are visually indicated, whether by mouse, keyboard, or touch. :focus-visible - Behavior: Applies styles only when the focus should be visible, such as using a keyboard or assistive technology. - Use Cases: Ideal for scenarios where you want to provide focus indicators only to keyboard and assistive technology users while avoiding unnecessary outlines for mouse and touch users, typically required by design. Accessibility Implications :focus - Pros: - Guarantees that all users can see when an element is focused, which is critical for accessibility. - Cons: - Can lead to a suboptimal experience for mouse users, as focus styles may appear unnecessarily during mouse interactions. :focus-visible - Pros: - Enhances user experience by showing focus indicators only when necessary, thus keeping the interface clean for mouse and touch users. - Tailors the experience for keyboard and assistive technology users, providing them with clear visual cues. - Cons: - Additional considerations may be required to ensure that focus indicators are not accidentally omitted, especially in older browsers that do not support :focus-visible. - There may be cases where you want to show focus indicators for all users, regardless of input method. Best Practices for Using :focus and :focus-visible To achieve the best accessibility and user experience, combining both :focus and :focus-visible in your CSS is often a good idea. Combining :focus and :focus-visible ` Here is a Stackblitz example of what such styling could look like for you to try out and play with. Additional Tips - Test with Keyboard and Assistive Technology: Ensure that your web application is navigable using a keyboard (Tab, Shift + Tab, etc.) and that focus indicators are visible for those who rely on them. It's never a bad idea to include accessibility testing in your e2e testing suite. - Provide Clear Focus Indicators: Make sure that focus indicators are prominent and easy to see. A subtle or hard-to-spot focus indicator can severely impact accessibility for users who rely on keyboard navigation. Conclusion The :focus-visible pseudo-class offers a more refined way to manage focus indicators, improving accessibility and user experience, particularly for keyboard and assistive technology users. By understanding the differences between :focus and :focus-visible, and applying best practices in your CSS, you can create more accessible and user-friendly web applications. Remember, accessibility should never be an afterthought. By thoughtfully applying focus styles, you ensure that all users, regardless of how they interact with your site, can easily navigate and interact....

Upgrading from Astro 2 to Astro 4 cover image

Upgrading from Astro 2 to Astro 4

Upgrading from Astro 2 to Astro 4 Astro is building fast. Right on the heels of their version 3 launch on August 30th, Astro version 4 launched on December 6th, 2023. They've built so fast, that I didn't even have a chance to try 3 before 4 came out! But the short time between versions makes sense, because the two releases are very complementary. Many Astro features introduced in version 3 as experimental are made stable by version 4. If, like me, you're looking at a two-version upgrade, here's what you need to know about Astro 3 and 4 combined. View Transitions Astro makes it easy to include animated transitions between routes and components with the component. You can add it to the of specific pages, or to your site-wide to be enabled across the entire site. No configuration is required, but you'll probably still want to configure it. Adding between pages effectively turns your site into a single-page application, animating in and out content on route change rather than downloading a new statically generated HTML document. You can further customize how specific components animate in and out with the transition:animate property. If you don't want client side routing for a specific link, you can opt out for that link with the data-astro-reload property. Image Optimization The way Astro works with images has changed a lot from version 2. If you were using @astrojs/image, then updating how you handle images is probably going to be the most time-consuming part of your Astro migration. Astro's and components have had API changes, which will require you to make changes in your usage of them. You should definitely check out the full image migration guide in the Astro docs for all of the details. But some of the details you should be aware of: - @astrojs/image is out, astro:assets is in - You get image optimization when you import images inside /src. This can change your entire image src referencing strategy. Optimization only works for images imported from inside /src, so you might want to relocate images you've been keeping inside the /public directory. - Importing an image file no longer returns the path as a string, and an ImageMetadata object with src, width, height, and format properties. If you need the previous behavior, add ?url to the import path. - Markdown documents can reference image paths inside /src for automatic image optimization, no need to use in MDX nor reference the root relative paths of images in the /public directory. - The and components have changes to properties. For example, aspectRatio is no longer a valid property because it is inferred from the width and height of images. A new pictureAttributes property lets you do things like add a CSS style string. - You can use a helper image schema validator in your content collection schemas. Dev Toolbar The Dev Toolbar is a new local development feature to help developers work with their interactive islands and to integrate with other tools. The Inspect option highlights what parts of the page are interactive, and lets you examine them. You can view their props and even open them directly in your editor. Audit checks for accessibility issues, such as missing alt attributes in images. And the Menu lets you use specific integrations. Currently only Storyblok and spotlight are available, but you can expect more integrations in the future. And if you don't want to wait, you can also extend the Dev Toolbar yourself with their API. If you don't like the Dev Toolbar, you can turn it off in the CLI with astro preferences disable devToolbar. Conclusion Astro has added a lot of cool features in 2 major back-to-back releases, and you should absolutely consider upgrading if you're still on version 2. Be prepared to modify how you've handled images, but also get excited to play with view transitions!...

“ChatGPT knows me pretty well… but it drew me as a white man with a man bun.” – Angie Jones on AI Bias, DevRel, and Block’s new open source AI agent “goose” cover image

“ChatGPT knows me pretty well… but it drew me as a white man with a man bun.” – Angie Jones on AI Bias, DevRel, and Block’s new open source AI agent “goose”

Angie Jones is a veteran innovator, educator, and inventor with over twenty years of industry experience and twenty-seven digital technology patents both domestically and internationally. As the VP of Developer Relations at Block, she facilitates developer training and enablement, delivering tools for developer users and open source contributors. However, her educational work doesn’t end with her day job. She is also a contributor to multiple books examining the intersection of technology and career, including *DevOps: Implementing Cultural Change*, and *97 Things Every Java Programmer Should Know*, and is an active speaker in the global developer conference circuit. With the release of Block’s new open source AI agent “goose”, Angie drives conversations around AI’s role in developer productivity, ethical practices, and the application of intelligent tooling. We had the chance to talk with her about the evolution of DevRel, what makes a great leader, emergent data governance practices, women who are crushing it right now in the industry, and more: Developer Advocacy is Mainstream A decade ago, Developer Relations (DevRel) wasn’t the established field it is today. It was often called Developer Evangelism, and fewer companies saw the value in having engineers speak directly to other engineers. > “Developer Relations was more of a niche space. It’s become much more mainstream these days with pretty much every developer-focused company realizing that the best way to reach developers is with their peers.” That shift has opened up more opportunities for engineers who enjoy teaching, community-building, and breaking down complex technical concepts. But because DevRel straddles multiple functions, its place within an organization remains up for debate—should it sit within Engineering, Product, Marketing, or even its own department? There’s no single answer, but its cross-functional nature makes it a crucial bridge between technical teams and the developers they serve. Leadership Is Not an Extension of Engineering Excellence Most engineers assume that excelling as an IC is enough to prepare them for leadership, but Angie warns that this is a common misconception. She’s seen firsthand how technical skills don’t always equate to strong leadership abilities—we’ve all worked under leaders who made us wonder *how they got there*. When she was promoted into leadership, Angie was determined not to become one of those leaders: > “This required humility. Acknowledging that while I was an expert in one area, I was a novice in another.” Instead of assuming leadership would come naturally, she took a deliberate approach to learning—taking courses, reading books, and working with executive coaches to build leadership skills the right way. Goose: An Open Source AI Assistant That Works for You At Block, Angie is working on a tool called goose, an open-source AI agent that runs locally on your machine. Unlike many AI assistants that are locked into specific platforms, goose is designed to be fully customizable: > “You can use your LLM of choice and integrate it with any API through the Model Context Protocol (MCP).” That flexibility means goose can be tailored to fit developers’ workflows. Angie gives an example of what this looks like in action: > “Goose, take this Figma file and build out all of the components for it. Check them into a new GitHub repo called @org/design-components and send a message to the #design channel in Slack informing them of the changes.” And just like that, it’s done— no manual intervention required. The Future of Data Governance As AI adoption accelerates, data governance has become a top priority for companies. Strong governance requires clear policies, security measures, and accountability. Angie points out that organizations are already making moves in this space: > “Cisco recently launched a product called AI Defense to help organizations enhance their data governance frameworks and ensure that AI deployments align with established data policies and compliance requirements.” According to Angie, in the next five years, we can expect more structured frameworks around AI data usage, especially as businesses navigate privacy concerns and regulatory compliance. Bias in AI Career Tools: Helping or Hurting? AI-powered resume screeners and promotion predictors are becoming more common in hiring, but are they helping or hurting underrepresented groups? Angie’s own experience with AI bias was eye-opening: > “I use ChatGPT every day. It knows me pretty well. I asked it to draw a picture of what it thinks my current life looks like, and it drew me as a white male (with a man bun).” When she called it out, the AI responded: > “No, I don’t picture you that way at all, but it sounds like the illustration might’ve leaned into the tech stereotype aesthetic a little too much.” This illustrates a bigger problem— AI often reflects human biases at scale. However, there are emerging solutions, such as identity masking, which removes names, race, and gender markers so that only skills are evaluated. > “In scenarios like this, minorities are given a fairer shot.” It’s a step toward a more equitable hiring process, but it also surfaces the need for constant vigilance in AI development to prevent harmful biases. Women at the Forefront of AI Innovation While AI is reshaping nearly every industry, women are playing a leading role in its development. Angie highlights several technologists: > “I’m so proud to see women are already at the forefront of AI innovation. I see amazing women leading AI research, training, and development such as Mira Murati, Timnit Gebru, Joelle Pineau, Meredith Whittaker, and even Block’s own VP of Data & AI, Jackie Brosamer.” These women are influencing not just the technical advancements in AI but also the ethical considerations that come with it. Connect with Angie Angie Jones is an undeniable pillar of the online JavaScript community, and it isn’t hard to connect with her! You can find Angie on X (Twitter), Linkedin, or on her personal site (where you can also access her free Linkedin Courses). Learn more about goose by Block....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co