DEV Community

Coco
Coco

Posted on

Amazing! Implementing artistic graphics with CSS

I’ve been wanting to write an article about the art of CSS creation for a long time. This article mainly introduces how to use CSS to quickly create beautiful CSS graphics with the help of CSS-doodle.

In short, CSS-doodle is a library based on Web-Component. It allows us to quickly create pages based on CSS Grid layouts and provides a variety of handy commands and functions (random, loops, etc.) that allow us to get different CSS effects with a set of rules. Take a look at its homepage — Home Page of CSS-doodle — and you can get started quickly in just 5min.

Create a Center Layout

All the tips in this article will revolve around this layout.

First, we need such a central layout. A simple HTML structure is as follows:

<div class="g-container">
    <div class="g-box"></div>
    <div class="g-box"></div>
    <div class="g-box"></div>
    <div class="g-box"></div>
    <div class="g-box"></div>
</div>
Enter fullscreen mode Exit fullscreen mode
.g-container {
    position: relative;
    width: 300px;
    height: 300px;
}
.g-box {
    position: absolute;
    top:50%;
    left: 50%;
    margin-left: -150px;
    margin-top: -150px;
    width: 100%;
    height: 100%;
    border: 1px solid #000;
}
Enter fullscreen mode Exit fullscreen mode

Use absolute positioning and margin to center all elements horizontally and vertically (because transform will be used later, so this method of horizontal and vertical centering is selected), the result is as follows:

Well, it looks flat, but based on this layout, we can derive very interesting patterns.

Change Elements' Size

The simplest thing is that we can change the size of an element.

CSS code is too tiring to write, so we simply rely on the pug HTML template engine and SASS.

div.g-container
    -for(var i=0; i<10; i++)
        div.g-box  
Enter fullscreen mode Exit fullscreen mode
$count: 10;
@for $i from 1 to $count + 1 {
    .g-box:nth-child(#{$i}) {
        --width: #{$i * 30}px;
        width: var(--width);
        height: var(--width);
        margin-left: calc(var(--width) / -2);
        margin-top: calc(var(--width) / -2);
    }
}
Enter fullscreen mode Exit fullscreen mode

Containing 10 child elements under the container, each of which increases in size incrementally, it is easy to get the following result.

Change Elements' Color

Next, we proceed to change the color of the element so that it takes on a gradient color progression, which could be border color.

@for $i from 1 to $count + 1 {
    .g-box:nth-child(#{$i}) {
         ...
         border-color: hsla(
            calc(#{$i * 25}),
            50%,
            65%,
            1
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Get this effect.

It is also possible to change the color of the background background:

@for $i from 1 to $count + 1{
    .g-box:nth-child(#{$i}) {
        ...
        background: hsla(
            calc(#{$i * 25}),
            50%,
            65%,
            1
        );
        z-index: #{$count - $i};
    }
}
Enter fullscreen mode Exit fullscreen mode

Change Elements' Angle

Okay, next, it's time to start transforming the angle, we use transform to rotate the element by different angles:

@for $i from 1 to $count + 1{
    .g-box:nth-child(#{$i}) {
        ....
        transform: rotate(#{$i * 7}deg);
    }
}
Enter fullscreen mode Exit fullscreen mode

The effect is as follows.

CodePen Demo -- CSS Pattern

OK, here, some basic concepts are introduced almost, in short, the use of multiple elements centered layout, change the size, color, transparency, angle, shadow, filter, blend mode, etc., etc., as long as you can think of, you can.

Next, let's introduce the other main character of this article - CSS-doodle.

CSS-doodle is a Web-Component based library. It allows us to quickly create pages based on CSS Grid layouts to achieve various CSS effects (or perhaps we can call it CSS art).

The code for the final effect is essentially CSS, and some of the specific concepts can be understood by clicking on the home page.

Use CSS-doole to achieve multi-element horizontal and vertical centering layout

Let's take the above layout and implement it again using CSS-doodle. To achieve a centered alignment of 50 elements, a simple declaration is needed as follows.

<css-doodle>
    :doodle {
        @grid: 1x50 / 100vmin;
    }
    @place-cell: center;
</css-doodle>
Enter fullscreen mode Exit fullscreen mode

What this means is that we declare a grid layout of 1x50 under a container of size 100vmin x 100vmin and use @place-cell: center to center them all horizontally and vertically, which means they will be stacked together.

This may not look good, so we'll set different sizes for each element and give them all a simple border.

<css-doodle>
    :doodle {
        @grid: 1x50 / 100vmin;
    }
    @place-cell: center;
    @size: calc(100% - @calc(@index() - 1) * 2%);
    border: 1px solid #000;
</css-doodle>
Enter fullscreen mode Exit fullscreen mode
  • @size: calc(100% - @calc(@index() - 1) * 2%) indicates the size of the width and height of each child element (or you can set the height and width separately), @index is a variable that indicates the number of the current element, from 1 - 50, indicating that each element is 2% of the container's height and width, 4% of the container's height and width all the way up to 100% of the container's height.
  • border: 1px solid #000 is the normal CSS code, there is no variable inside, it works on each element

The effect is as follows.

Oh No, the eyes are starting to glaze over. In this way, we have quickly implemented the graphical effect that was generated using HTML code and tedious CSS during the previous layouts.

Create CSS Art

Next, the wonderful CSS art begins.

Change the rotation angle of the element and the border color

Let's use the above code to continue down the page, first changing the base color of the overall container to black for better presentation, and then changing the rotation angle of the elements. Each element is rotated by 30deg x @index.

The code is very short and looks like this.

<css-doodle>
    :doodle {
        @grid: 1x100 / 100vmin;
    }
    @place-cell: center;
    @size: calc(100% - @calc(@index() - 1) * 1%);
    transform: rotate(calc(@index() * 30deg));
    border: 1px solid #fff;
</css-doodle>
Enter fullscreen mode Exit fullscreen mode

Not very good, then we try to set a different border color progressively for each element, and the transparency opacity decreases, and here we will use the hsla color representation.

<css-doodle>
    :doodle {
        @grid: 1x100 / 100vmin;
    }
    @place-cell: center;
    @size: calc(100% - @calc(@index() - 1) * 1%);
    transform: rotate(calc(@index() * 30deg));
    border: 1px solid hsla(
        calc(calc(100 - @index()) * 2.55), 
        calc(@index() * 1%), 
        50%,
        calc(@index() / 100)
    );
</css-doodle>
Enter fullscreen mode Exit fullscreen mode

And look at the effect.

All mapping has some color difference, you can click into the Demo to see~

Wow, the first piece of work looks pretty good.

Of course, each different angle can produce a different effect, through CSS-doodle, you can quickly generate different random values, randomly generate different effects. Let's change the above code a bit, changing the transform line to introduce a random value:

<css-doodle>
    :doodle {
        --rotate: @r(0, 360)deg;
    }
    transform: rotate(calc(@index() * var(--rotate)));
</css-doodle>
Enter fullscreen mode Exit fullscreen mode
  • @r(0, 360)deg, which generates a random number between 0 and 360, which can be followed directly by a unit, which becomes a random angle value
  • transform: rotate(calc(@index() * var(--rotate)), using the calc rule to introduce a random CSS variable, but of course, without refreshing the page, the value is fixed every time

This way, we can get a different effect each time we refresh the page (of course, CSS-doodle is optimized to add just a few lines of code to refresh the effect by clicking on the page), and the effect after the transformation, we can get a new effect each time we click:

CodePen Demo -- CSS Doodle - CSS Magic Pattern

Strongly recommend you click into the Demo and feel it yourself with a click of the mouse :)

Set Different Background Colors

Okay, let's change our thinking again, this time instead of changing the color of the border, we control the odd numbered elements and the even numbered elements by means of a selector, giving them different background colors.

<css-doodle>
    :doodle {
        @grid: 1x100 / 100vmin;
    }
    @place-cell: center;
    @size: calc(100% - @calc(@index() - 1) * 1%);
    transform: rotate(calc(@index() * 60deg));

    background: rgba(0, 0, 0, calc((@index * 0.01)));
    @even {
        background: rgba(255, 255, 255, calc((@index * 0.01)));
    }
</css-doodle>
Enter fullscreen mode Exit fullscreen mode

Using @even {} you can quickly select an element with an even number and give it a white background, while an odd numbered element is given a black background, see the effect.

In the same way, we can assign random values to the rotation angle of transform and use the black and white overlay to see what happens at different angles:

CodePen Demo -- CSS Doodle - CSS Magic Pattern

Of course, in the random process, you can also pick your favorite ones and keep them.

CSS-doodle supports many ways to introduce multiple graphics on one page, like this.

CodePen Demo -- CSS-doodle Pure CSS Pattern

Summary

A small summary, to generate different patterns, in fact ** just need to find the ability to generate different lines, or modeling pattern graphics, they will be different sizes, different rotation angle, different colors and transparency superimposed on each other can be **.

In this case, some possible ideas.

  • What would it look like to use only one-way borders?
  • The borders that appear are solid, what if they were replaced by a dashed line dashed? Maybe we could add border-radius
  • text-decoration also supports some kinds of underscores, so we can try using them too!

OK, putting the above idea into practice, we can get a variety of shapes drawn with various lines. They might look like this.

Of course, the effect can be randomized every time, as long as we make good use of the random parameters, you can poke into the following demo to feel it:

CodePen Demo -- CSS-doodle Pure CSS Patterns

Clip-path && Drop-shadow

Hey, when it comes to creating different lines and patterns, it's important to mention two other interesting properties in CSS. They are clip-path and fitler: drop-shadow().

Hmmm? What does that mean. Let's have a simple demo, using Clip-path, we can crop out different element shapes. For example, to implement a simple polygon.

div {
    width: 300px;
    height: 300px;
    clip-path: polygon(50% 0%, 90% 20%, 100% 60%, 75% 100%, 25% 100%, 0% 60%, 10% 20%);
    background: #333;
}
Enter fullscreen mode Exit fullscreen mode

The effect is as follows.

Then using this idea, we can try to use clip-path to crop out various different shapes for overlaying.

In CSS-doodle Shapes, there are a very large number of clip-path shapes built in for us to choose from:

We pick one at random:

Applying the above rules, try to implement a graphic:

<css-doodle>
    :doodle {
        @grid: 1x100 / 100vmin;
    }
    @place-cell: center;
    @size: calc(100% - @calc(@index() - 1) * 1%);
    background: hsla(
        calc(calc(100 - @index()) * 2.55), 
        calc(@index() * 1%), 
        65%,
        calc(@index() / 100)
    );
    clip-path: @shape(
        fill-rule: evenodd;
        split: 200;
        scale: .45;
        x: cos(2t) + cos(π - 5t);
        y: sin(2t) + sin(π - 5t);
    );
</css-doodle>
Enter fullscreen mode Exit fullscreen mode

This time instead of rotating the different angles, just giving each layer a different background base color, and being able to get something like:

CodePen Demo -- CSS Doodle - CSS Magic Pattern

Use Clip-path and Drop-shadow To Create Different Lines Patterns

OK, the above is using clip-path to create different patterns, but how do you get the different lines?

Not so fast. Using drop-shadow, you can create different shadows for Clip-path cropped shapes, but there are some structural constraints.

div {
    position: relative;
    width: 300px;
    height: 300px;
    filter: drop-shadow(0px 0px 1px black);

    &::after {
        content: "";
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        right: 0;
        background: #fff;
        clip-path: polygon(50% 0%, 90% 20%, 100% 60%, 75% 100%, 25% 100%, 0% 60%, 10% 20%);
    }
}
Enter fullscreen mode Exit fullscreen mode

We need to apply filter: drop-shadow(0px 0px 2px black) on top of the parent element of the element that utilizes clip-path, and the element that utilizes clip-path: must have background in order to attach a shadow effect to the clipped element.

The above code is as follows.

OK, perfect, this way we have greatly enriched our line library, and by applying the above line rules, a whole new wave of patterns will be created.

CodePen Demo -- CSS-doodle Pure CSS Pattern - clip-path - drop-shadow

OK, limited to space, not to expand one by one, interested in the above Demo Fork a copy to try for themselves. There are a lot of interesting patterns waiting to be generated.

Finally, let's take a look at the work of CSS-doodle author, Yuan Chuan, who used the above technique:

CodePen Demo -- css doodle art

Finally

More wonderful CSS technical articles are summarized in my Github -- iCSS.

And maybe you will love my CodePen, which has a large number of amazing CSS effects.

Well, that's all for this article, I hope it helps you. :)

Top comments (0)