Anatomy of a CSS Corgi Ear
Tags: css, html, codepen
Published: 2020-05-23 13:46:16

Last week I shared that I was embarking on a journey to [create 100 CSS images in 100 days](https://dev.to/s_aitchison/join-me-for-100-days-of-pure-css-48fo) - I started with little to no knowledge (beyond the more everyday CSS I do for frontend development work), and so needless to say every day I am learning a lot. 

I thought I'd share some of those learnings as I progress through the 100 days, and this post is about the ears of this pupper that I made for Day 2:

{% codepen https://codepen.io/aitchiss/pen/zYvmWrp %}

I found the process to create those ear shapes quite challenging, but these are the steps that eventually worked for me.

Disclaimer: I doubt that this is the "best" way to create these shapes - like I say I'm still learning lots 😄

## Step 1: Create the basic ear shape

First up I declare two div elements. I gave both of them a shared class 'ear' and their own class 'left-ear' and 'right-ear' - as so:

```html
  <div class="left-ear ear"></div>
  <div class="right-ear ear"></div>
```

For reasons that I'll go into during a later step, I'm going to use the `::before` and `::after` pseudo elements to actually create the orange and pink parts of the ear, rather than the main '.ear' div itself.

### A quick interlude on ::before and ::after

These are pseudo elements that allow you to insert more content onto the page using CSS only. You can read more about it at this [CSS Tricks article](https://css-tricks.com/almanac/selectors/a/after-and-before/), but the tl;dr is that what we'll end up with will be a little like:

```html
<div class="left-ear ear">
  ::before element appears here
  ::after element appears here
</div>
```

Bear in mind this order of appearance when creating CSS images, especially if you're looking to overlay one on top of the other. In this ear example, we want the pink inner ear to appear on top of the orange outer ear, so we will use the `::before` element for the orange outer ear, and the `::after` element for the inner pink.

NB: for a `::before` or `::after` element to be visible on the page, you need to add  `content: ''`. Otherwise CSS detects there is no content, so does nothing with the styles.

### Back to creating the ear triangles

There are a few ways in CSS to create triangles. One option is to use the `border-width` property on a div with 0 height and width. There's a nice article on CSS Tricks about this: [CSS Triangle]([https://css-tricks.com/snippets/css/css-triangle/](https://css-tricks.com/snippets/css/css-triangle/)).

For this task however I used `clip-path`, which literally 'clips' a rectangular `div` to only show what's inside of a specific shape. Creating clip-paths manually from the top of your head can be a bit tricky, but there's a great tool called [Clippy]([https://bennettfeely.com/clippy/](https://bennettfeely.com/clippy/)) that can generate one for you - I've been using this a lot!

My CSS and progress so far then is:

```css
.ear {
  position: absolute;
  top: 10px;
  height: 220px;
  width: 140px;
  background: var(--background-color);
}

.left-ear {
  left: 120px;
}

.right-ear {
  right: 120px;
}

/* Shared main orange outer ear styles */
.ear::before {
  content: '';
  position: absolute;
  background: var(--orange-fur-color);
  width: 100%;
  height: 100%;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
```
![In progress shot of the ears - two orange triangles side by side](https://dev-to-uploads.s3.amazonaws.com/i/aa6247ac0bohe8k7px1h.png)

## Step 2 - add the inner-ear pink

Now I can make use of the `::after` pseudo element to add the pink inner ear. I didn't want the inner triangle to be too perfectly a replica of the outer triangle, so I changed up the `clip-path` property ever so slightly to give a different angle. I then offset the position of the inner pink so that the inner and outer ear have slightly different thickness to each other.

Here's the CSS for the inner ears, and what the work in progress looks like so far now:

```css
.ear::after {
  content: '';
  bottom: 10px;
  position: absolute;
  background: pink;
  width: 95%;
  height: 80%;
  clip-path: polygon(50% 0, 6% 100%, 100% 100%);
}

.left-ear::after {
  right: -20px;
}

.right-ear::after {
  left: 20px;
}
```
![In progress CSS image - pink triangles overlayed on the orange triangles, side by side](https://dev-to-uploads.s3.amazonaws.com/i/11mz8rfck5j5yonelpxf.png)

## Step 3 - rotate the ears

I don't want the ears to be quite so straight-up-and-down, so I rotated them 20 degrees in each direction, as so:

```css
.left-ear {
  left: 120px;
  transform: rotate(-20deg);
}

.right-ear {
  right: 120px;
  transform: rotate(20deg);
}
```
![In progress image - both triangle ears now rotated 20 degrees towards the outside edges of the canvas](https://dev-to-uploads.s3.amazonaws.com/i/j43g0nt00ftswf5izuhy.png)

(don't worry about the very bottom of the ears overlapping  - I'll fix that in a later step)

## Step 4 - Mask the pointiness

Corgis have super cute big pointy ears, but they're not spikey! I wanted to mask some of the pointy-ness and not have quite so perfect a triangular shape, and this is the reason I haven't used the main `.ear` div element for the orange and pink detail.

I can mask the top point of the ear by adding a border-radius to that parent element, and hiding the overflow, so our `.ear` class now looks like:

```css
.ear {
  position: absolute;
  top: 10px;
  height: 220px;
  width: 140px;
  border-radius: 50% 50% 0 0;
  overflow: hidden; 
  background: var(--background-color);
}
```

I'm going to move my outer ears (`.ear::before`) up a bit now using `top: -25px` to push the triangle up enough that it overflows the parent element, which is going to hide the overflow of its curved edges.

Even better, I'd like to give the outer edge of the ears a more straight shape, so we don't have such exact triangles all the way down. In the CSS snippet above, you'll see I only set the `border-radius` to 50% on the top two corners, with the lower two corners remaining straight/square. Now when I increase the size of my outer ears and tweak the positioning to move the triangle further towards the outside edges, it's forced to overflow again, this time over straight edges. 

The CSS for my orange outer ears now looks like:

```css
.ear::before {
  content: '';
  position: absolute;
  top: -25px;
  background: var(--orange-fur-color);
  width: 130%;
  height: 120%;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.left-ear::before {
  left: -25px;
}

.right-ear::before {
  right: -25px;
}
```
At this point I also tweaked the inner pink ear position to fit a bit nicer now that the outer ear has changed shape slightly:

```css
.left-ear::after {
  right: 8px;
}

.right-ear::after {
  left: 8px;
}
```

... which all results in:

![Finished ear shapes - now with straightened outside edges and slightly rounded tops](https://dev-to-uploads.s3.amazonaws.com/i/t3wmei09q6un12ewzzgu.png)

## Hang on, what?

To help illustrate how the changes in this step helped create the overall shape you see, take a look at how this would look if the `.ear` class had a white background:

![Replica of the previous image, but this time the ears are shown sitting inside two white blocks, with a rounded domed top and a square bottom](https://dev-to-uploads.s3.amazonaws.com/i/czyqfqrx6755ymrn4wz8.png)

Or if it had both a white background, and I removed the `overflow: hidden` line from the CSS:

![Copy of the previous image, but now you can see the pointy corners of the ears overflowing outside of the white shape](https://dev-to-uploads.s3.amazonaws.com/i/0jg44cdbxzf9tm9rkw23.png)

I think this makes it a bit easier to see how `overflow:hidden` combined with the `border-radius` properties helped me to create the end shape. 

## The ears are done!

So that's the corgi ears. Check out the CodePen with the final product to see where the other elements came into play (which I found a lot more straightforward). 

I learned a lot trying to accomplish this shape, and I'm sure there are far better ways to do it - every day I'm learning new things and I look forward to looking back on this one and realising all the ways I could have done it more efficiently!!

{% codepen https://codepen.io/aitchiss/pen/zYvmWrp %}