My Current Frontend Progess

I have finished 8 challenges on Frontend Mentor. All of them are vanilla HTML/CSS without Javascript. I think it is a good time give them a review, sum up the elements and methods I used, and see what I can improve in the future.

QR Code Component

Preview

This is my first frontend 'project'. It contains an image and two blocks of words. It keeps the same layout in both mobile and desktop.

HTML

Let's take a look of the html file.

<div class="container">
  <img src="images/image-qr-code.png" alt="A qrcode linking to FrontEnd Master"/>
  <div class="text">
    <h1 class="text-preset-1">
      Improve your front-end skills by building projects
    </h1>
    <p class="text-preset-2">
        Scan the QR code to visit Frontend Mentor and take your coding skills to the next level
    </p>
  </div>
</div>

The first impression is that these class names are vague. container is a good start. The following text did not well demonstrate that it is a part of the container. This can be improved by using the BEM convention. Like this

<div class="container">
  <img />
  <div class="container__content">
    <h1></h1>
    <p></p>
  </div>
</div>

Then I noticed that I implemented font presets as isolated classes here, see text-preset-1 and text-preset-2. It is fine, but scalability might be a problem. Imagine that there are thousands of blocks of texts, I need to add class for each of them.

The typography of a page should be consistent. That is to say, one should define its basic style for h1, h2, and so on. If some element had its customed style, it deserves a class name.

CSS

Let's analyse the CSS file.

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    text-align: center;
}

:root {
    --color-slate-900: #1F314F;
    --color-slate-500: #68778D;
    --color-slate-300: #D5E1EF;
    --color-white: #FFFFFF;

    --text-preset-1-font-family: "Outfit", sans-serif;
    --text-preset-1-font-weight: bold;
    --text-preset-1-font-size: 22px;
    --text-preset-1-line-height: 120%;
    --text-preset-1-letter-spacing: 0px;
    --text-preset-2-font-family: "Outfit", sans-serif;
    --text-preset-2-font-weight: normal;
    --text-preset-2-font-size: 15px;
    --text-preset-2-line-height: 140%;
    --text-preset-2-letter-spacing: 0.2px;

    --spacing-200: 16px;
    --spacing-300: 24px;
    --spacing-500: 40px;
}

This is the common start of all of my CSS files. It removes all the margins and paddings, in order to set them by myself later and keep consisten in different browsers. It also sets boxes to border-box, which complies my mental model of paddings and margins. Setting variables in :root allows any sub-elements to use them.

.text-preset-1 {
    font-family: var(--text-preset-1-font-family);
    font-weight: var(--text-preset-1-font-weight);
    font-size: var(--text-preset-1-font-size);
    line-height: var(--text-preset-1-line-height);
    letter-spacing: var(--text-preset-1-letter-spacing);
    color: var(--color-slate-900);
    text-align: center;
}

.text-preset-2 {
    font-family: var(--text-preset-2-font-family);
    font-weight: var(--text-preset-2-font-weight);
    font-size: var(--text-preset-2-font-size);
    line-height: var(--text-preset-2-line-height);
    letter-spacing: var(--text-preset-2-letter-spacing);
    color: var(--color-slate-500);
    text-align: center;
}

Just as I said before, I should put them to h1 and p. Speaking of them, at the end of the file, I did

.text h1 {
    margin: 0;
    word-break: break-word;
    white-space: normal;
    overflow-wrap: break-word;
}

.text p {
    margin: 0;
    word-break: break-word;
    white-space: normal;
    overflow-wrap: break-word;
}

First, margins have been removed twice. This is redundant and should be removed. Second, I couldn't remember why I added these wrapping properties here. I haven't used them since then. Maybe they are unnecessary here?

body {
    background-color: var(--color-slate-300);
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

The line height: 100vh is a problem. I set it because I want to put the card in the center of the page. Otherwise, the height of body is the height of the card. This is fine for small components. But it would cause overflow for long pages. So the solution here should be min-height: 100vh.

The next part, display: flex; ..., is probably the CSS snippet I found myself repeating the most. The purpose of them is to place the children in the center.

Let's review the card:

.container {
    width: min-content;
    background-color: var(--color-white);
    padding: var(--spacing-200) var(--spacing-200) var(--spacing-500);
    border-radius: 20px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: stretch;
    gap: var(--spacing-300);
    box-shadow: 0 4px 4px 0 rgb(0, 0, 0, 0.25);
}

.container img {
    width: 288px;
    height: 288px;
    border-radius: 10px;
    flex-shrink: 0;
}

.container .text {
    weight: 100%;
    box-sizing: border-box;
    padding: 0px var(--spacing-200);
    display: flex;
    flex-direction: column;
    justify-content: start;
    align-items: center;
    gap: var(--spacing-200);
}

One of the most annoying problems is how to control the right width and height. The detailed discuss is in other article. The conclusion is that 1. set the width of container is necessary; 2. set the width of .text is unnecessary, and there is even a typo.

The problem is, what value should I set? Here min-content is a good choice since we fixed the size of img to 288px * 288px.

There are a lot of needless properties here:

  1. align-items: stretch. The children are either fixed width or already stretched. center is better.
  2. flex-shrink: 0.

The revised version should be:

.container {
    width: min-content;
    background-color: var(--color-white);
    padding: var(--spacing-200) var(--spacing-500);
    border-radius: 20px;
    box-shadow: 0 4px 4px 0 rgb(0, 0, 0, 0.25);
    
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--spacing-300);

}

.container img {
    width: 288px;
    height: 288px;
    border-radius: 10px;
}

.container .text {
    box-sizing: border-box;
    padding: 0 var(--spacing-200);
    
    display: flex;
    flex-direction: column;
    justify-content: start;
    align-items: center;
    gap: var(--spacing-200);
}

Conclusion

How to write a neat and maintainable CSS? A better quesiton is, how to analysis a page in a systematic way? My current thought is: look them from top to bottom, outside to inside, general to specific. And for each part, consider it from appearance, to typography, then to the layout.