DEV Community

Cover image for CSS Art: June was made for happiness
Tanveer Singh Mahendra
Tanveer Singh Mahendra

Posted on • Updated on

CSS Art: June was made for happiness

This is a submission for Frontend Challenge v24.04.17, CSS Art: June.

Inspiration

The idea for this project blossomed from a casual conversation with my friend Ritul Choudhary over Discord. In search of inspiration, Ritul found several poems about June, and this one by Annette Wynne resonated deeply with him. Captivated by the poem's imagery, we decided to transform its essence into a visual representation.

To bring our vision to life, we enlisted the help of our talented artist friend Niranjan Bharati. He skillfully translated the poem's elements onto a 100px x 200px canvas, creating a beautiful piece of pixel art that encapsulates the poem's serene and joyful spirit.

The artwork depicts a tender moment between a mother and her daughter on a summer afternoon. They are seated in a lush grassland, surrounded by pink tulips and fluttering butterflies, while the mother reads a book to her daughter. The scene is set against a backdrop of majestic mountains and a sky dominated by a large, fluffy cloud, partially veiling the sun. This imagery perfectly captures the poem's celebration of June's simple pleasures and the happiness found in nature.

Mother

Demo


Github: Source Code

The Art Process

Our journey began with a simple idea and evolved into a beautiful piece of digital art. Here are the steps we took to create our pixel art masterpiece:

  1. Initial Sketch:
    Stage 1
    We started with a basic sketch to outline the elements we wanted to include. This initial sketch helped us visualize the overall composition and placement of key elements like the mother, daughter, butterflies, and the surrounding nature.

  2. Defining Shapes and Colors:
    Stage 2
    Next, we began defining the shapes and adding basic colors. This stage was crucial in establishing the structure and color palette of the artwork. We focused on ensuring the characters and elements were easily recognizable and aligned with the mood of the poem.

  3. Adding Details:

    Stage 3
    With the basic shapes and colors in place, we moved on to adding details. This included refining the characters, enhancing the background elements, and adding textures to make the scene more vibrant and lively.

  4. Final Touches:
    Stage 4
    In the final stage, we added the finishing touches to the artwork. This involved adjusting colors, smoothing out lines, and ensuring all elements were cohesive. The result was a beautiful pixel art piece that captured the essence of Annette Wynne's poem.

Journey and What I Learned

Why 100px x 200px, you might ask? Well, as this was my first CSS art project, I wanted to keep it simple and draw it in pixel-art form. I followed this useful tutorial to get started. Soon, I realized that creating a 100px by 200px image would require me to write 20,000 individual values to generate the art. The art size restriction we had set earlier wasn't small enough. But here we were, so I decided to automate the CSS pixel values generation.

from PIL import Image

def pixel_to_em(pixel, em_scale):
    return pixel * em_scale

def image_to_css_box_shadow(image_path, width_em, height_em):
    img = Image.open(image_path)
    img = img.convert('RGBA')
    width_px, height_px = img.size

    # Calculate em scaling factors based on provided width and height
    em_scale_x = width_em / width_px
    em_scale_y = height_em / height_px

    box_shadows = []

    for y in range(height_px):
        for x in range(width_px):
            r, g, b, a = img.getpixel((x, y))
            if a > 0:  # If pixel is not transparent
                x_em = pixel_to_em(x, em_scale_x)
                y_em = pixel_to_em(y, em_scale_y)
                hex_color = f'#{r:02x}{g:02x}{b:02x}'
                box_shadows.append(f'{x_em}em {y_em}em {hex_color}')

    return ', '.join(box_shadows)

if __name__ == "__main__":
    image_path = 'final-art.png'
    width_em = 100  # The width of the image in em units
    height_em = 200  # The height of the image in em units
    css_box_shadow = image_to_css_box_shadow(image_path, width_em, height_em)
    print(f'box-shadow: {css_box_shadow};')

Enter fullscreen mode Exit fullscreen mode

The Python code above takes the constraint of 1em as a base unit in CSS and translates the pixel values into em counterparts. The logic is to iterate over the image, pick individual pixel values, and convert them into a CSS box-shadow property in the format: 'x'em 'y'em #xxxxxx. Then, the script joins them with a comma separator. I ran the Python script and saved the output in a text file to later copy-paste into the style.css file.

This worked perfectly, and we were able to see the CSS code come to life! While discussing the results, we felt that the dimensions resembled a bookmark. Why not transform this into a digital bookmark? So, that's what we started looking into. I found this amazing tutorial by w3schools and applied the learnings to our project.

The poem was the perfect candidate for the back side of the digital bookmark. I added a hover interaction on the parent <div> of the flip card to allow everyone to appreciate the inspiration behind the artwork. As a final touch, applied the Noto Sans font by Google to the back side of the bookmark.

Through this project, I learned the importance of variables, and automation in CSS art projects. Automating repetitive tasks not only saves time but also allows for more complex and detailed creations. Additionally, incorporating interactive elements like the flip card adds a layer of engagement and depth to the final piece.

If you have any questions, feel free to ask them in the comments.

Top comments (5)

Collapse
 
thumbone profile image
Bernd Wechner

Love it. Amazing how you can use boxshadows and generate them automatically form a image in Python. Love it.

I do think that as lovely as Annette Wynne's poem is, that she wrote pre-globalisation and from a southerner's perspective it's oddly temperate hemispherist! πŸ˜†

Google suggests I just invented that term! Cool. It needs inventing πŸ˜‰.

In case it's not clear June only has that significance in the northern hemisphere temperate zone between the tropic of cancer and the arctic circle. Out side of that band June either has little meaning or the opposite completely. Here June is most definitely for winds and stress ;-) we look to January for the blessings Wynne is dreaming of.

Collapse
 
schmoris profile image
Boris

This is madness! Congratulations πŸ˜ƒπŸ˜ƒπŸ˜ƒπŸ˜ƒπŸ˜ƒ

Collapse
 
gargeebanerjee profile image
Gargee Banerjee

Woahhhh!! Amazing 😢😢

Collapse
 
jennavisions profile image
Jenna

Beautiful work! 😊

Congratulations on winning the CSS Art: June Challenge! πŸŽ‰"

Keep up the amazing work! πŸ‘

Collapse
 
koza_brajamagenta profile image
Koza Brajamagenta

Thats insane. What a dedication