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.
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:
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 2018When 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:
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:
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;
}
📝 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:
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:
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:
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:
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:
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:
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:
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 👇