Complex Shapes in CSS

Jane HW
4 min readJun 30, 2019

Last weekend my friend introduced me to the GIPF Project, a series of two-person abstract strategy games where the movement of the pieces mimic natural elements.

I had been wanting to make a game for a while, so I picked Dvonn, the towers game, where players stack pieces like towers and the way pieces are captured and taken off the board resembles the way fire spreads.

I was excited about digging into the game play, but I immediately realized this project would require blazing trails in CSS before I could fire up a game engine.

That’s a lot of hexagons

Getting Started

My board is essentially nested arrays of rows and columns with one div for each space, so I needed to use CSS magic to shape my divs. A quick trigonometry search showed me that the height of a hexagon is √3 * the width so I set those as the dimensions of each div. I added a background color and a decently sized margin so you could see the results.

.tile {
width: 100px;
height: 57.8px; /* ~1.73 * width */
background: @navy;
margin: 50px; /* For demonstration purposes*/
}
#Basic

From here I learned I would need to dig into using the ::before and ::after pseudo elements so here’s a quick interlude to explain what I learned about them.

An Aside of Pseudo Importance

In CSS, pseudo classes are attributes which affect the entire element, like “hover,” “link,” or “first-child,” while pseudo elements only affect a portion of the element like “first-line,” “first-letter,” or “before.”

While CSS2 ignored the distinction between the two, in CSS3, this distinction is made by the number of colons used to denote the attribute. Pseudo classes should use one (“a:hover”) while pseudo elements should use two (“.tile::before”). Unfortunately, IE8 doesn’t support double colon syntax so most people continue to use one colon regardless of the usage.

I will be using two colons because this is a personal project. I do not use IE8.

::Before and ::After

These pseudo elements allow you to add content directly before or after an HTML element. The attribute “content” defaults to none, so you need to add something or there will be no display. Because I am more interested in shapes than text, I added an empty string here but filled in the borders with color so we could see what we are working with.

These pseudo elements will fill in things before or after the content of whatever element you have placed them on (so the additional markup is inserted into the same div, not outside of it).

Here is what I found experimenting with border colors:

.tile::before {
bottom: 100%;
border-left: 50px solid @coral; /* borders are half width */
border-right: 50px solid @coral;
border-top: 50px solid @tan;
border-bottom: 50px solid @tan;
}
The borders you would normally use on an element are all available for use on a pseudo element

One thing to note, is that the before pseudo-element can affect the size of the element.

The before pseudo element here increases the height by a quarter

However, from here it was clear that I could simply hide the borders in the before and after pseudo elements to get the desired effect. Here is the full code and the effect.

.tile {
position: relative;
width: 100px;
height: 57.8px; /* ~1.73 * width */
background: @navy;
margin: 50px; /* For demonstration purposes*/
}
.tile::before {
bottom: 100%;
border-bottom: 50px solid @coral; /* borders are half width */
}
.tile::after {
top: 100%;
border-top: 50px solid @coral;
}
.example::before,
.example::after
{
content: "";
position: absolute;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
}
Perfect hex

Final Touches

After I had spun enough CSS magic to get a perfect hex, I played around a bit with flexbox to get my rows and columns in order, skewed the tiles slightly and rotated the whole board to achieve the desired effect.

Coming soon to a git repository near you

I would still like to perfect the rotations so it looks a little cleaner, but this is definitely a good enough start to get to work on the game play.

📝 Read this story later in Journal.

👩‍💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.

--

--