Making Art with CSS 🎨

5th November 2020

One of my main aims for this website was to make sure that it was visually unique and pleasing to use. Among many things that can make or break a website's design, I think the background is crucial to get right. It's often one of the few elements of a website that consistently remains throughout the user's experience.

The background I ended up with I think works really well as it is striking while also letting the content in front of it take the focus. It was made possible using some CSS magic with just a few lines of code thanks to css-doodle. It's an amazing little component which lets you get very creative so I thought I'd share how I used it!

How css-doodle works


The idea behind css-doodle is quite straightforward. It creates a grid where its height and width are defined by the user. With this, you can use whatever CSS you like, to either customise the grid itself, or the cells inside it.

The properties of grid can be targeted with the selector :doodle, while all code outside of this block will target every cell in the grid individually.

<css-doodle>
  :doodle {
    @grid: 20x35;
    @size: 100% 100%;
    position: fixed;
    background: #F8C9CD;
    grid-gap: 5px;
  }

  background: rgba(255, 255, 255, 1);
</css-doodle>

@grid lets you choose the number of rows and columns for it, while @size lets you decide the dimensions of the grid itself. Here I have chosen 100% for height and width to span across the screen.

grid-gap introduces a gap of any size to all directions for each cell. Now, with the colours of pink and white used for the grid and the cells respectively, we can quickly see how our code shapes up to be visually.

blog/making-art-with-css/doodle1

How I made my background


So now we have two things we can work on: the grid and the cells inside it. At the moment the cells are of a uniform size, shape and colour. However, things get interesting when we start choosing which cells we want to target with our styling.

css-doodle selectors allow you to quickly choose cells in a number of ways. You can target every even-indexed cell (@even), odd-indexed cell (@odd), the nth cell (@nth(n)), every odd-indexed row (@row(odd)) and more. I found that choosing cells by random (using @random(n) where n decides the probability of it being chosen) created the most interesting effects.

Using @random, I applied a border-top and a border-left with a chance of 40% of being used by any given cell. In the code, you can see that the borders are each applied inside a separate @random selector. This is to make sure that the application of border-top and border-left is mutually exclusive which helps to make the pattern look less repetitive.

<css-doodle>
  :doodle {
    @grid: 20x35;
    @size: 100% 100%;
    position: fixed;
    background: #F8C9CD;
    grid-gap: 5px;
  }

  @random(0.4) {
    border-top: 1px solid white;
    opacity: @rand(0.2, 0.4)
  }

  @random(0.4) {
    border-left: 1px solid white;
    opacity: @rand(0.2, 0.4)
  }

  background: rgba(255, 255, 255, 1);
  transform: rotate(@p(±45deg));
</css-doodle>

The border itself is white, but with a random opacity between 0.2 and 0.4. This is done with the function @rand provided by css-doodle. This is not to be confused with @random which is solely responsible for selection of cells rather than picking parameters. Similarly, the colours of the cells are randomly selected in a darker shade of pink than the grid colour, also with a low random opacity.

All of this put together creates a tiled pattern with subtly accented cells. The different low levels of opacity makes it aethetically pleasing while being suitable to be used as a background. To finish it off, I rotate each cell by +/-45 degrees alternately to have the tiles line up in a zig-zag fashion, shown below on the right image.

The random nature of the styling means that it looks different every time it is loaded. A nice touch when it comes to switching between the pages of the website.

blog/making-art-with-css/doodle2

There's so much more you can do with it, and this is clearly just scratching the surface. You can even animate cells using keyframes, which I tried for this website. However, since I was using it as a background for the entire page, even animating just a few number of cells would heavily impact performance.

Although this is all just simple CSS, it's all put together in one component with the tools and functions you need to make some really cool stuff 😎

Check out the doodle on CodePen to play around with it!