質問
html & css coding. Training yourself can help you get better much faster.
Update: 

Introduce

  • The State Of Pixel Perfection
  • Ten modern layouts in one line of CSS

The State Of Pixel Perfection

When was the last time you heard the term “Pixel Perfection”? Depending on who you work with, the last time could range from today or years ago. Pixel perfection is a term coined by designers and clients as they request that their design mockups must reflect the design and be an exact copy of it. For me, I’m still hearing this term until this day from some clients. Should we pixel-perfect an implementation of a design mockup?

What Is Pixel Perfection?

Pixel perfection is the process of implementing a web design mockup in HTML and CSS, taking into consideration that the coded result must be an exact match of the design mockup. Consider the following figure:

The original design was made on Sketch app, and the coded implementation is being viewed on Google Chrome browser. Do you notice any differences? Here are some of them:

The header height
The spacing below the header
The number of cards per row
Such differences can affect the final result, and can easily be considered as imperfect implementation. In reality, is it imperfect? I will answer this question in an upcoming section.

Look & Feel

A few years ago, I learned the term look & feel, which means, in the context of web design, how a website looks in terms of a UI perspective, and how it feels in terms of functionality and interactivity.

Before diving into examples, let me show you the following two figures. The first one is YouTube. In the second one, I tweaked the look & feel and tried to make it like Twitter.

Youtube

Youtube With Twitter Style

What I changed is the following:

  • Header background and shadow
  • Search input
  • Iconography
  • The primary color

Those small changes can fool you if you’re not focused enough. This is what I mean by look & feel. Let’s dive into more detailed examples.

Consider the following figure which shows various design components for a website.

Let’s take the card component as an example, and show a good and a bad implementation of it.

Did you notice the differences between the two cards? If you don’t see any difference between them, then you’re in for a treat. Let’s explore that!

The border thickness is different
The difficulty tag is closer to the top and left edges
The image height is smaller
Different font sizes (Larger)
Inconsistent border-radius
The above differences significantly affected the result, and they are only for one component, the card. Your developer friend might say that these differences are subtle and they don’t matter. For one component, that might be correct. However, can you imagine these subtle changes on a large scale? Eventually, you will end up implementing an imperfect result.

Consider the below interactive figure. Switch between the design and code results to see the differences.

As a UI designer, you can’t ignore those differences, and I agree with you. You worked hard on the spacing, sizes, and alignment. Adding to that, the above differences are easy to fix. However, the reason developers make UI mistakes and inconsistencies can differ depending on:

The design
Project timeline
The developer’s design and CSS skills
Good attention to detail
I don’t think the developer doesn’t know how to do such fixes that can make the final result closer to the original design. For me, I consider that every developer has a mindset. When the developer know both design and development, you will notice fewer design differences. On the contrary, if the developer has no design skills at all, then expect that the differences will be higher.

Deciding If A Coded Result Is Perfect Or Not
Let’s get to the real question. How to decide if a coded result is perfect without being too picky? The reason I explained about the look & feel concept previously is that we can follow it. Instead of aiming for a perfect coded result, we can aim for matching the look & feel of the design.

Let’s get back to the card component, but for this time, the differences are acceptable.

The differences are subtle (The card on the right):

The difficulty tag is smaller, which is fine
The grey border is gone
Such details don’t matter that much, and they are fine. What’s even important is agreeing on the look & feel of the design. Let’s explore that in detail.

As someone who does design and front-end development, there is a moment that draws a smile on my face while coding a design that I built. It’s the moment where I have two tabs opened:

  1. The first one is for the original design (as an image). This could be in InVision or Figma Preview.
  2. And the second tab is for the localhost of my machine

When I reach the moment where I can’t differentiate between the design and the localhost tabs, I can be sure that the look & feel is the same, and my coded result is ready. By ready, I don’t mean that the exact measures and widths are 100% identical, but the general look & feel that can fool you easily while moving between the two tabs.

General Tips For Developers

Train Your Eye To Attention For Detail

Since it’s not possible to train yourself to catch little UI details overnight. Training yourself can help you get better much faster. Here are some ideas:

  • Clone a UI of a popular website like Twitter, for example, and try to make it as close as possible. Make sure to get feedback on the accuracy of it.
  • Practise makes perfect. The more you implement designs in HTML & CSS, the more your eye will learn about the details.
  • Play Can’t Unsee game. It’s a fun game that will challenge your UI design detail knowledge.

Use A Ruler In The Browser

Checking for alignment in the browser is still not provided by default. However, you can use some browser extensions that provide the ability to add guides. Grid ruler for Chrome and Firefox can do the job.

Notice how the search input is not aligned with the user avatar. The reason could be an unneeded margin or padding. Whatever the reason, not everyone can notice such issues.

Ten modern layouts in one line of CSS

This post highlights a few powerful lines of CSS that do some serious heavy lifting and help you build robust modern layouts.

Modern CSS layouts enable developers to write really meaningful and robust styling rules with just a few keystrokes. The talk above and this subsequent post examine 10 powerful lines of CSS that do some serious heavy lifting.

01. Super Centered: place-items: center

For the first 'single-line' layout, let's solve the biggest mystery in all of the CSS land: centering things. I want you to know that it's easier than you think with place-items: center.

.parent {
  display: grid;
  place-items: center;
}

02. The Deconstructed Pancake: flex:

Next we have the deconstructed pancake!

By using Flexbox for this effect, you won't need media queries to adjust the placement of these elements when the screen resizes.

The flex shorthand stands for: flex: .

Because of this, if you want your boxes to fill out to their size, shrink on smaller sizes, but not stretch to fill any additional space, write: flex: 0 1 . In this case, your is 150px so it looks like:

.parent {
  display: flex;
}

.child {
  flex: 0 1 150px;
}

If you do want the boxes to stretch and fill the space as they wrap to the next line, set the to 1, so it would look like:

.parent {
  display: flex;
}

.child {
  flex: 1 1 150px;
}

03. Sidebar Says: grid-template-columns: minmax(, ) …)

.parent {
  display: grid;
  grid-template-columns: minmax(150px, 25%) 1fr;
}

Add this as a value of grid-template-columns with the following value: minmax(150px, 25%) 1fr. The item in the first column (the sidebar in this case) gets a minmax of 150px at 25%, and the second item (the main section here) takes up the rest of the space as a single 1fr track.

04. Pancake Stack: grid-template-rows: auto 1fr auto

Unlike the Deconstructed Pancake, this example does not wrap its children when the screen size changes. Commonly referred to as a sticky footer, this layout is often used for both websites and apps, across mobile applications (the footer is commonly a toolbar), and websites (single page applications often use this global layout).

Adding display: grid to the component will give you a single column grid, however the main area will only be as tall as the content with the footer below it.

To make the footer stick to the bottom, add:

.parent {
  display: grid;
  grid-template-rows: auto 1fr auto;
}

This sets the header and footer content to automatically take the size of its children, and applies the remaining space (1fr) to the main area, while the auto sized row will take the size of the minimum content of its children, so as that content increases in size, the row itself will grow to adjust

05. Classic Holy Grail Layout: grid-template: auto 1fr auto / auto 1fr auto

For this classic holy grail layout, there is a header, footer, left sidebar, right sidebar, and main content. It's similar to the previous layout, but now with sidebars!

For this classic holy grail layout, there is a header, footer, left sidebar, right sidebar, and main content. It's similar to the previous layout, but now with sidebars!

To write this entire grid using a single line of code, use the grid-template property. This enables you to set both the rows and columns at the same time.

The property and value pair is: grid-template: auto 1fr auto / auto 1fr auto. The slash in between the first and second space-separated lists is the break between rows and columns.

.parent {
  display: grid;
  grid-templa
  te: auto 1fr auto / auto 1fr auto;
}

As in the last example, where the header and footer had auto-sized content, here the left and right sidebar are automatically sized based on their children's intrinsic size. However, this time it is horizontal size (width) instead of vertical (height).

06. 12-Span Grid: grid-template-columns: repeat(12, 1fr)

Next we have another classic: the 12-span grid. You can quickly write grids in CSS with the repeat() function. Using: repeat(12, 1fr); for the grid template columns gives you 12 columns each of 1fr.

.parent {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
}

.child-span-12 {
  grid-column: 1 / 13;
}

Now you have a 12 column track grid, we can place our children on the grid. One way to do this would be to place them using grid lines. For example, grid-column: 1 / 13 would span all the way from the first line to the last (13th) and span 12 columns. grid-column: 1 / 5; would span the first four.

Another way to write this is by using the span keyword. With span, you set the starting line and then how many columns to span into from that starting point. In this case, grid-column: 1 / span 12 would be equivalent to grid-column: 1 / 13, and grid-column: 2 / span 6 would be equivalent to grid-column: 2 / 8.

.child-span-12 {
  grid-column: 1 / span 12;
}

07. RAM (Repeat, Auto, MinMax): grid-template-columns(auto-fit, minmax(, 1fr))

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

You are using repeat again, but this time, using the auto-fit keyword instead of an explicit numeric value. This enables auto-placement of these child elements. These children also have a base minimum value of 150px with a maximum value 1fr, meaning on smaller screens, they will take up the full 1fr width, and as they reach 150px wide each, they will start to flow onto the same line.

With auto-fit, the boxes will stretch as their horizontal size exceeds 150px to fill the entire remaining space. However, if you change this to auto-fill, they will not stretch when their base size in the minmax function is exceeded:

.parent {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

08. Line Up: justify-content: space-between

For the next layout, the main point to demonstrate here is justify-content: space-between, which places the first and last child elements at the edges of their bounding box, with the remaining space evenly distributed between the elements. For these cards, they are placed in a Flexbox display mode, with the direction being set to column using flex-direction: column.

This places the title, description, and image block in a vertical column inside of the parent card. Then, applying justify-content: space-between anchors the first (title) and last (image block) elements to the edges of the flexbox, and the descriptive text in between those gets placed with equal spacing to each endpoint.

.parent {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

09. Clamping My Style: clamp(, , )

Here's where we get into some techniques with less browser support, but have some really exciting implications for layouts and responsive UI design. In this demo, you are setting the width using clamp like so: width: clamp(, , ).

This sets an absolute min and max size, and an actual size. With values, that can look like:

.parent {
  width: clamp(23ch, 50%, 46ch);
}

The minimum size here is 23ch or 23 character units, and the maximum size is 46ch, 46 characters. Character width units are based on the font size of the element (specifically the width of the 0 glyph). The 'actual' size is 50%, which represents 50% of this element's parent width.

What the clamp() function is doing here is enabling this element to retain a 50% width until 50% is either greater than 46ch (on wider viewports), or smaller than 23ch (on smaller viewports). You can see that as I stretch and shrink the parent size, the width of this card increases to its clamped maximum point and decreases to its clamped minimum. It then stays centered in the parent since we've applied additional properties to center it. This enables more legible layouts, as the text won't be too wide (above 46ch) or too squished and narrow (less than 23ch).

This is also a great way to implement responsive typography. For example, you could write: font-size: clamp(1.5rem, 20vw, 3rem). In this case, the font-size of a headline would always stay clamped between 1.5rem and 3rem but would grow and shrink based on the 20vw actual value to fit the width of of the viewport.

This is a great technique to ensure legibility with a minimum and maximum size value, but remember it is not supported in all modern browsers so make sure you have fallbacks and do your testing.

10. Respect for Aspect: aspect-ratio: /

And finally, this last layout tool is the most experimental of the bunch. It was recently introduced to Chrome Canary in Chromium 84, and there is active effort from Firefox in getting this implemented, but it is not currently in any stable browser editions.

I do want to mention this, though, because it is such a frequently met problem. And that is just simply maintaining the aspect ratio of an image.

With the aspect-ratio property, as I resize the card, the green visual block maintains this 16 x 9 aspect ratio. We are Respecting the Aspect Ratio with aspect-ratio: 16 / 9.

.video {
  aspect-ratio: 16 / 9;
}

To maintain a 16 x 9 aspect ratio without this property, you'd need to use a padding-top hack and give it a padding of 56.25% to set a top-to-width ratio. We will soon have a property for this to avoid the hack and the need to calculate the percentage. You can make a square with 1 / 1 ratio, a 2 to 1 ratio with 2 / 1, and really just anything you need for this image to scale with a set size ratio.

.square {
  aspect-ratio: 1 / 1;
}

While this feature is still up and coming, it it a good one to know about as it resolves a lot of developer strife that I have faced many times myself, especially when it comes to video and iframes.

Conclusion

Thank you for following this journey through 10 powerful lines of CSS. To learn more, watch the full video, and try out the demos yourself.

この記事が気に入ったら応援お願いします🙏
2
ツイート
LINE
Developer
Price Rank Dev
I use Next.js (React) and Firebase (Firestore / Auth) for development. We are also developing APIs for Ruby on Rails and GraphQL. Our team members are 6 Vietnamese and Japanese engineers.