DEV Community

Cover image for 3D Ham Sandwich Animation
FrontEndWebDeveloping
FrontEndWebDeveloping

Posted on

3D Ham Sandwich Animation

This is a submission for DEV Challenge v24.03.20, CSS Art: Favorite Snack.

Inspiration

Ham sandwiches are my favorite lunch. Especially with Louisiana hot sauce mixed with the mayonnaise.

Here's My Code:

HTML

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Ham Sandwich</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <section>
            <div class="top-bread">
                <div class="top-crust">
                    <div class="top-center"></div>
                </div>
            </div>
            <div class="mayo-and-hot-sauce">
                <div class="blob blob-one"></div>
                <div class="blob blob-two"></div>
                <div class="blob blob-three"></div>
                <div class="blob blob-four"></div>
                <div class="blob blob-five"></div>
                <div class="blob blob-six"></div>
                <div class="blob blob-seven"></div>
                <div class="blob blob-eight"></div>
            </div>
            <div class="ham-edge-one">
                <div class="ham-layer-one"></div>
            </div>
            <div class="ham-edge-two">
                <div class="ham-layer-two"></div>
            </div>

            <div class="bottom-bread">
                <div class="bottom-crust">
                    <div class="bottom-center"></div>
                </div>
            </div>
        </section>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

CSS

*{
    box-sizing: border-box;
}
:root{
    --ham-background: linear-gradient(
        45deg,
        rgb(180,100,120),
        rgb(220,140,160),
        rgb(180,100,120),
        rgb(220,140,160)
    );
    --ham-border-background: linear-gradient(
        45deg,
        rgb(200,120,140),
        rgb(240,160,180),
        rgb(200,120,140),
        rgb(240,160,180)
    );
    --ham-background-two: linear-gradient(
        45deg,
        rgb(220,140,160),
        rgb(180,100,120),
        rgb(220,140,160),
        rgb(180,100,120)
    );
    --ham-border-background-two: linear-gradient(
        45deg,
        rgb(240,160,180),
        rgb(200,120,140),
        rgb(240,160,180),
        rgb(200,120,140)
    );
}
body{
    display: grid;
    align-items: center;
    justify-content: center;
    height: 100vh;
    width: 100vw;
}
section{
    height: 300px;
    width: 600px;
    display: grid;
    justify-content: center;
    transform-style: preserve-3d;
    transition: transform 2.5s;
    transform: rotate3d(15, 1, 1, 40deg);
}
section:hover{
    transform: rotate3d(1, 1, 1, 25deg) matrix3d(
    3, 0, 0, 0,
    0, 3, 0, 0,
    0, 0, 3, 0,
    100, 100, 0, 4
  );
}
.top-bread{
    display: grid;
    z-index: 5;
}
.top-crust{
    width: 350px;
    height: 130px;
    transform: skewX(-50deg);
    border-radius: 25px 50px 5px 50px;
    background-color: rgb(150,90,60);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0px 40px 20px 0px;
}
.top-center{
    height: 100%;
    width: 100%;
    background: rgb(220,170,120);
    border-radius: 25px 30px 5px 25px;
    box-shadow: inset 2px 1px 5px 3px rgb(150,90,60);
}
.mayo-and-hot-sauce{
    height: 130px;
    width: 350px;
    display: grid;
    z-index: 4;
    margin-top: -163px;
    margin-left: 0px;
}
.blob{
    background: rgb(255,180,170);
    box-shadow: inset 0px 0px 4px 2px rgb(200,120,140);
}
.blob-one{
    width: 40%;
    margin-left: 245px;
    margin-top: 15px;
    border-radius: 0px 10px 25px 0px;
    height: 35px;
    transform: rotate(10deg);
}
.blob-two{
    width: 80%;
    height: 40px;
    margin-left: 45px;
    margin-top: 25px;
    border-radius: 0px 10px 90px 0px;
    transform: rotate(2deg);
}
.blob-three{
    width: 80%;
    height: 20px;
    width: 30px;
    margin-left: 20px;
    margin-top: 0px;
    border-radius: 0px 0px 25px 50px;
    transform: rotate(20deg);
}
.blob-four{
    width: 80%;
    height: 20px;
    width: 50px;
    margin-left: 220px;
    margin-top: -20px;
    border-radius: 0px 0px 50px 50px;
    transform: rotate(10deg);
}
.blob-five{
    width: 50px;
    height: 25px;
    margin-left: 90px;
    margin-top: -22px;
    transform: rotate(-20deg);
    border-radius: 0px 0px 115px 80px;
}
.blob-six{
    height: 40px;
    width: 50px;
    margin-left: -50px;
    margin-top: -35px;
    border-radius: 16px 0px 10px 20px;
    transform: rotate(-20deg);
}
.blob-seven{
    height: 30px;
    width: 60px;
    margin-top: -30px;
    margin-left: 130px;
    border-radius: 0px 0px 25px 40px;
    transform: rotate(-15deg);
}
.blob-eight{
    height: 60px;
    width: 30px;
    margin-left: 330px;
    margin-top: -120px;
    border-radius: 0px 0px 20px 0px;
    transform: rotate(20deg);
}
.ham-edge-one{
    width: 374px;
    height: 130px;
    transform: skewX(-50deg);
    border-radius: 10px 30px 10px 25px;
    background: var(--ham-border-background);
    padding: 0px 3px 3px 0px;
    z-index: 3;
    margin-top: -180px;
    margin-left: -15px;
}
.ham-layer-one{
    width: 370px;
    height: 128px;
    background: var(--ham-background-two);
    border-radius: 10px 27px 10px 24px;
}
.ham-edge-two{
    width: 374px;
    height: 130px;
    transform: skewX(-50deg);
    border-radius: 10px 30px 10px 25px;
    background: var(--ham-border-background-two);
    padding: 0px 3px 3px 0px;
    z-index: 2;
    margin-top: -205px;
    margin-left: -14px;
}
.ham-layer-two{
    width: 370px;
    height: 128px;
    background: var(--ham-background);
    border-radius: 10px 27px 10px 24px;
}
.bottom-bread{
    display: grid;
    z-index: 1;
    margin-top: -220px;
}
.bottom-crust{
    width: 350px;
    height: 130px;
    transform: skewX(-50deg);
    border-radius: 25px 50px 5px 50px;
    background-color: rgb(150,90,60);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0px 40px 20px 0px;
}
.bottom-center{
    height: 100%;
    width: 100%;
    background: rgb(220,170,120);
    border-radius: 25px 30px 5px 25px;
    box-shadow: inset 2px 1px 5px 3px rgb(150,90,60);
}
@keyframes spin {
    from {
        transform:matrix3d();
    }
    to {
        transform: rotate(360deg);
    }
}
Enter fullscreen mode Exit fullscreen mode

Code Link

Here is a link to the code in CodePen: myLink

Journey

I started by using a simple paint app I had already built to draw a rough sketch of the sandwich, just to clear things up in my mind. Then I started on my HTML. I chose the class names according to the part of the sandwich I intended each element to represent. Except for the section, to hold the whole sandwich, (and the body) I used div elements for the whole creation.

Once I was done with the HTML I moved to the CSS. I started by defining my * selector's properties. I set the box-sizing and also I gave all the elements a border: 1px solid black property and attribute. From there I started at the top of the sandwich and worked my way down (except that I styled both pieces of bread at once), styling parents, then children. Once everything but the .mayo-and-hot-sauce element were styled, I put my sandwich together by setting the margin properties to appropriate values.

Then, I started on the .mayo-and-hot-sauce element. I added .blobs and styled them, until it looked good to me.

Finally, I added the animation to the section element. I've had little practice with CSS animations, so I had to play with it a while before it was to my liking.

With that, the project was finished. I learned several things. One would be, how to use the border-image property. It's really neat. I used it to give my slices of ham a gradient border to match their background properties. I also learned about the rotate3D and matrix3D properties of CSS.

In building the project I strove to make the sandwich appear 3D. This, along with realistic looking gradients, I would say are it's main high points, and the goal's I tried to achieve.

MIT License

Top comments (5)

Collapse
 
cicirello profile image
Vincent A. Cicirello

Hi. Here is a tip related to DEV's markdown editor. It supports syntax highlighting. You can enable syntax highlighting by indicating the language on the line with the opening backticks. For example:

```html
<body>
<h2>Hello World</h2>
</body>
```
Enter fullscreen mode Exit fullscreen mode

Produces:

<body>
<h2>Hello World</h2>
</body>
Enter fullscreen mode Exit fullscreen mode

You can do the same for CSS or any other language. Just put language name right after opening backticks without any spaces.

Collapse
 
softwaredeveloping profile image
FrontEndWebDeveloping

Thankyou. 😊

Collapse
 
cicirello profile image
Vincent A. Cicirello

You're welcome

Collapse
 
best_codes profile image
Best Codes

Ooh, it looks so yummy!
Great job!

Collapse
 
softwaredeveloping profile image
FrontEndWebDeveloping

Thanks @best-codes. I appreciate it. If any of you have improvements to suggest please do so.