Creating Patterns Using CSS & the <css-doodle /> Web Component

<css-doodle /> is a Web Component that makes it easy to create all kinds of patterns for your web designs. It’s a great example of what can be achieved using modern web technologies like custom elements, shadow DOM and CSS Grid.

You can see an example of <css-doodle /> in action at the top of category pages on this site.

Setup

You can simply include the <css-doodle /> script from cdnjs into your pages:

<script src="https://cdnjs.cloudflare.com/ajax/libs/css-doodle/0.2.3/css-doodle.min.js"></script>

Alternatively, you can also add the component to your project using Yarn or npm:

$ npm install css-doodle

# or, using Yarn:
$ yarn add css-doodle

Then you can simply add pattern sections to your pages using the <css-doodle /> custom element with some CSS rules passed-in as children:

<css-doodle>
  ...
</css-doodle>

Basic Examples

Behind the scenes <css-doodle /> creates a grid of elements using CSS Grid layout. Let’s create a simple grid of 5 rows by 8 columns with a width value that’s 100% the width of its parent container and a height of 15rem:

:doodle { @grid: 5x8 / 100% 15rem; } :after { content: "@index()" } background: pink; margin: .5rem;
<css-doodle>
  :doodle {
    @grid: 5x8 / 100% 15rem;
  }
  :after {
    content: "@index()"
  }
  background: pink;
  margin: .5rem;
</css-doodle>

Notice how we get a special :doodle pseudo-selector to style the grid container itself. Within that pseudo-selector we used the @grid attribute to define the number of cells in the grid and the total size of the grid container.

You can also see that we made use of another special function, @index(), to add the current cell index as the content to each cell’s :after pseudo-element.

You can also define the number of cells using the grid attribute on the element directly:

<css-doodle grid="5x8">
  ...
</css-doodle>

Let’s now push this example a little bit further to create an interesting pattern:

:doodle { @grid: 8 / 25rem 25rem; @shape: circle; background: var(--bg3); max-width: 90%; } @keyframes turn { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes glow { 50% { transform: scale(1.1); } 100% { transform: scale(1); } } @random { animation: glow .9s ease-out infinite; } :hover { animation: turn .9s ease-out infinite; } @shape: @pick('triangle', 'clover 4', 'hexagon', 'diamond', 'heart'); background: @pick('coral', 'orange', 'pink', 'blueviolet', 'darkslateblue'); margin: .5rem; opacity: calc(@rand(1, 10) / 10);
<css-doodle>
  :doodle {
    @grid: 8 / 20rem 20rem;
    @shape: circle;
    background: var(--bg3);
    max-width: 90%;
  }

  @keyframes turn {
   0% {
    transform: rotate(0deg);
   }
   100% {
    transform: rotate(360deg);
   }
  }

  @keyframes glow {
    50% {
      transform: scale(1.1);
    }
    100% {
      transform: scale(1);
    }
  }

  @random {
    animation: glow .9s ease-out infinite;
  }

  :hover {
    animation: turn .9s ease-out infinite;
  }

  @shape: @pick('triangle', 'clover 4', 'hexagon', 'diamond', 'heart');
  background: @pick('coral', 'orange', 'pink', 'blueviolet', 'darkslateblue');
  margin: .5rem;
  opacity: calc(@rand(1, 10) / 10);
</css-doodle>

That example is a lot more interesting, yet still quite simple to implement. We made use of a few more special functions that are made available by <css-doodle />:

  • @shape: Allows to shape the cell or the container using any of a number of predefined shapes.
  • @pick: Picks one of the provided values at random.
  • @rand: Returns a random value between the provided range.

And we also made use of another special selector:

  • @random: Selects some cells at random.

As you can see, the component also accepts any valid CSS rules, even our animation definition using @keyframes. Our global CSS variables are also accessible.

There’s quite a few more special selectors, properties and functions that are available, making it possible to create pretty much any pattern imaginable. Have a look at the official docs for a full reference.

JavaScript API

There’s a simple JavaScript API that lets you get or set the number of rows and columns or update the doodle with new values. For example, let’s create a simple doodle that refreshes its value when clicked on:

:doodle { @grid: 8 / 25rem 25rem; @shape: circle; background: var(--bg3); max-width: 90%; } @keyframes turn { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } :hover { animation: turn .9s ease-out infinite; } @shape: @pick('triangle', 'clover 4', 'hexagon', 'diamond', 'heart'); background: @pick('coral', 'orange', 'pink', 'blueviolet', 'darkslateblue'); margin: .5rem; opacity: calc(@rand(1, 10) / 10);
<css-doodle class="my-doodle">
  ...
</css-doodle>

<script>
const myDoodle = document.querySelector('.my-doodle');

myDoodle.addEventListener('click', () => {
  myDoodle.update();
});
</script>

Since our doodle contained values for cell shape and opacity that are picked at random, updating it changes the pattern each time.

Browser Support

Currently <css-doodle /> works out of the box in Chrome and Safari without the need for any polyfill. To make it work in non-supporting browsers, refer to this article about polyfilling for custom elements.

Alternatively, you may want to opt for graceful degradation and just hide your patterns on non-supporting browsers. For example, the following adds a no-doodle-support class to the body element if custom elements or shadow DOM are not supported:

if (!window.customElements || !document.head.attachShadow) {
  document.body.classList.add('no-doodle-support');
}

Then you can simply set display: none on the css-doodle elements that are within a body with the no-doodle-support class:

.no-doodle-support css-doodle {
  display: none;
}

Further Reading

Check out the following links to learn more:

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#