Dribbble Designs in Code (part 1 — Venue Landing Page)

This is the first in a series of posts on coding designs from Dribbble. The next post is already out —check out part 2 — Editorial Exploration.

Vlad Sabev
9 min readJun 14, 2018

Being a web developer, I will admit to occasionally having that anxious feeling when receiving a new design mockup, thinking something like:

  • “This will take too long to implement with the technology we have today and all the old browsers we have to support”
  • “This design is messy and inconsistent and won’t work even for simple use cases”
  • “Designers have zero consideration about all the hacks I’ll have to add to get that layout to work”

I’m assuming that’s because of a deep-rooted fear of failure which, if overcome, could ultimately help me become a better professional.

Having recently started working more closely with designers, I’ve come to appreciate their process — and while it can take a bit of compromise on both sides to get a concept to a working state, a creative design can significantly push my abilities as a developer.

To dispel my own fears and doubts, I browsed around some of my colleagues’ designs with the intention of picking one to implement. It had to be simple enough for me to realistically be able to do it in a few hours, while at the same time interesting enough to learn a thing or two.

As this is the first time I’ve challenged myself this way, I’m starting small with this design by Boyan Kostov:

Venue Landing Page by Boyan Kostov for Perspektiva — Dribbble

Required Knowledge

To effectively follow along with this article, you’ll need the following skills:

  • HTML — basic
  • SVG — basic
  • CSS — intermediate

If you want to dive straight into the code instead, you can find it on CodePen.

📝 The blending modes used in this example have only been tested in Chrome, Firefox, and Safari, so if you run it in another browser chances are it will look different!

Content

Text

For me, the first step in implementing a design is adding the content. Generally speaking, if you have the opportunity to copy the data from somewhere (or use the same API), that’s great!

In my case, I typed it by hand:

Underwater
Expo 2018
When you're underwater with goggles on, a couple of your senses are taken away, and it becomes this purely visual thing. It's just you and yourself.7-24 July 2018
Arrow Icon
Ticket Icon

Which looks somewhat underwhelming:

It can be marginally improved if we add some wrapping elements:

<div class="main">
<h1 class="title">
Underwater
<span class="subtitle">Expo 2018</span>
</h1>

<p class="text">When you're underwater with goggles on, a couple of your senses are taken away, and it becomes this purely visual thing. It's just you and yourself.</p>

<div class="bottom">
<div class="date">7-24 July 2018</div>
<div class="arrow">Arrow Icon</div>
<div class="ticket">Ticket Icon</div>
</div>
</div>

Notice the distinct classes title and subtitle — as the second title line should be blending with the background, we’ll need it to be a separate element. Also, the bottom content is all wrapped by an element, because it has a horizontal layout, which we’ll need to implement.

Something else of note is that the h1 and p elements have additional styling in some browsers that changes the spacing (I’m looking at you, Chrome 🤨), we can add the following rules so we can style our elements using standard margins and padding instead:

h1, p {
-webkit-margin-before: 0;
-webkit-margin-after: 0;
}

📝 As I used CodePen to implement this design, it has an option to reset those styles for me, so I didn’t need to include the code above. For more info see Eric Meyer’s Reset CSS.

Another option is to use Normalize.css, which preserves some sane defaults instead of removing all styles like Reset CSS does. For a more detailed discussion on the differences, see this StackOverflow question.

Icons

Using CodePen’s assets feature, which links to the Material Design Icons, we can easily find what we need by searching for arrow and then ticket.

📝 The ones I ended up using are a bit different than those in the design, which is fine, since this is an exercise in styling.

Something we can do to get closer to the intended look is change the colors and add a circle to each of the icons. To account for the extra space that the circles would take within the SVG, we’ll also change the viewBox property. Here’s the arrow icon, which is white and has a transparent fill for the circle:

<div class="arrow">
<svg viewBox="-10 -10 45 45">
<circle cx="12" cy="12" r="20" stroke="white" stroke-width="1" fill="transparent" />
<path d="M11,4H13V16L18.5,10.5L19.92,11.92L12,19.84L4.08,11.92L5.5,10.5L11,16V4Z" stroke="white" fill="white" />
</svg>
</div>

As for the ticket button, we have a semi-transparent black icon placed over a circle with a yellowish fill. We can use the fill-opacity attribute to achieve that, and also implement a transform with rotation. Notice the angle and origin, which rotates the path to the left around its center — rotate(-45 12,12).

<div class="ticket">
<svg viewBox="-10 -10 45 45">
<circle cx="12" cy="12" r="20" fill="yellow" />
<path d="M15.58,16.8L12,14.5L8.42,16.8L9.5,12.68L6.21,10L10.46,9.74L12,5.8L13.54,9.74L17.79,10L14.5,12.68M20,12C20,10.89 20.9,10 22,10V6C22,4.89 21.1,4 20,4H4A2,2 0 0,0 2,6V10C3.11,10 4,10.9 4,12A2,2 0 0,1 2,14V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V14A2,2 0 0,1 20,12Z" fill="black" fill-opacity="0.2" transform="rotate(-45 12,12)" />
</svg>
</div>

And here’s what that looks like in the browser, with a gray background for the main element and some sizing for the icons so we can see them:

The finished content of the design

Good, now that we’re done with the content we can switch to only using CSS to style the page!

Styling

Background

The background color of the main element is #0a2066, and here’s the entire image:

Their own comfortable photo by Pan Da chuan (@dachuan) on Unsplash

To achieve the desired effect, we have to adjust the background image position, repeat, size, and blend mode, and make the text white:

.main {
background-blend-mode: difference;
background-color: #0a2066;
background-image: url("https://images.unsplash.com/photo-1488953994029-e6a7ba3348f7");
background-position: center bottom -32vw;
background-repeat: no-repeat;
background-size: cover;
color: #ffffff;
}
After adding the background image

📝 While I had access to the original PSD, I didn’t have Photoshop, so the easiest way to find the color, image, and blending mode was to ask!

A 2-minute conversation with the designer can provide both of you with some useful insights, save hours of research, and help you create a better product!

Bottom

The part of the page containing the date and icons is laid out horizontally instead of vertically. This means we can use CSS tools like Flexbox or Grid.

🙏 Shout out to Dave Geddes for his massively successful online courses on both Flexbox and Grid, respectively Flexbox Zombies and Grid Critters.

Flexbox Zombies helped me master this CSS tool after having used it for years and still hesitating when to use what. No more! I highly recommend it, and it’s even free!

Thanks, Dave!

In this case we only need to lay out elements in one direction, which means Flexbox should suffice. We also need to center the arrow icon between two elements. On first look, there’s a very simple way to do that by using justify-content: space-between. But here’s what we actually get:

Centering using justify-content: space-between

Ignoring the differences in font size and margins, notice how the arrow icon in the screenshot above is off-center compared to the original design below:

Centering in the original design

It seems that’s not quite what we’re aiming for. In fact, when the elements on both sides of a flex container have a different width, justify-content: space-between doesn’t place the central element at the exact center of the parent. Instead, the space remaining after subtracting the content’s width is divided between the elements. The same goes for using margin-right: auto and margin-left: auto.

What we can do to avoid this is add text-align: right to the ticket element, then either use flex: 1 on the date and ticket elements, or alternatively use Grid on their parent with columns of 1fr auto 1fr. Here’s how the design looks with more accurate centering:

Centering using a combination of flex: 1 and text-align: right

Font

The font used is Avenir, which is commercial. Once again, since the goal is not 100% fidelity, we can use Google Fonts and compare side by side with the original design to find a viable replacement:

Comparing Google fonts with the original design

After typing the title text and adjusting the options, the Lato font with weights of 400 and 900 seems to be close — the edges are a bit more rounded, but letters are thick and imitate the look and feel of the design well enough.

Sizing and Spacing

As this is a large and spacious design (at least on desktop resolutions, which is the only design we have), we can use the well supported vw (viewport width) unit for sizing and spacing instead of px or rem.

In basic terms, 1vw represents 1% of the current width of the entire page. We’ll use it for the following properties:

  • Margin
  • Padding
  • Font size
  • Letter spacing
  • Line height
  • Width (for the icons)

That looks like a lot of guesswork, where do we even start?

Fortunately, there’s a trick that I really like which makes it much easier to get immediate feedback when implementing a design:

body {
background-image: url("https://cdn.dribbble.com/users/29468/screenshots/4658658/attachments/1052263/underwater.jpg");
background-repeat: no-repeat;
background-size: contain; /* or `cover`, depends on the design */
}
.main {
opacity: 0.8;
}

By putting the original design as a background image of the body and making the main element semi-transparent, we can see the differences between the two with every change we make and discuss them with our design team to reach a solution.

📝 Making sure that differences between the code and the original design are understood and accepted by everyone is important. Even more so when working with a client who may have certain expectations and be surprised with the end result!

After tweaking the CSS for a while, it starts to look something like this when overlaid with the original design:

Overlayed on top of the original design

Blending the Subtitle

We’re really close now! The only thing left is to get the second row of the title blended with the background — so let’s apply mix-blend-mode: overlay; to it:

Our implementation of the blended title text

Looks like the title text in the original design is somewhat brighter —and another quick conversation with the designer later, I find out he achieved that by copying the text and layering it twice:

Original design blended title text, layered twice

While this might work when getting creative with the look and feel of a page in a tool like Photoshop or Sketch, it can be a headache to implement in code. This is why it’s important for different professionals to sit down and have a discussion about the way some parts of the design were made.

📝 In this case, I tried a few different approaches, including using text shadow and pseudo-elements, none of which yielded the results I needed. In the end I was stuck with a somewhat dimmer text — which I think still looks great.

At the Finish Line

Here’s the end result from all that hard work:

And, once again, the original design — for comparison:

Finally, the actual code running on CodePen:

Conclusion

Congrats, you made it all the way through! 🎈

Personally, after years of focusing on enterprise applications, developer tools, and software architecture, I’m very happy I could flex my HTML & CSS muscles. I’ve come to appreciate the usefulness of practicing a skill in isolation using little exercises like this one!

How about you — did you have any new insights into the process of implementing designs? Or how developers and designers can work better together?

Let me know in the comments 👇

--

--