Hardpart of CSS part 1

Mordern CSS toolkits developers should have

ยท

9 min read

Hardpart of CSS part 1

CSS can sometimes feel like a very inconsistent language. Why is this snippet I've used countless times suddenly behaving differently?! It turns out a lot is going on under the hood. CSS is a collection of complex layout algorithms with all sorts of hidden mechanisms and implicit behaviors. When we take the time to learn how CSS works, the language starts to make a lot more sense, and the unpleasant surprises become much less common. In this blog, we'll dig into common misunderstandings about CSS and see if we can fill in some gaps in our mental model of the language.

1) Logical Properties

I have covered this in one of my blog posts; you can check it out here

2) Pseudo-element for custom animation

A pseudo-element creates a faux element. Let's have a look at this example

<style>
  h1::before {
  content: "๐Ÿ˜€";
}
</style>
<h1>
  Hello World
</h1>
<!-- But why do we have to go extra mile ? 
   why can't we just write <h1>  ๐Ÿ˜€ Hello World </h1>

Differences between pseudo-element and pseudo-class

To make a long story short, a pseudo-element used to add specific content to an element (::before,::after) or they can style the specific content of an element (::first-letter,last-letter)

On the contrary, the Pseudo-class used to alter the element's style as some of the specific states

Put everything we know into practice

First of all, we will create a simple button

<style>
  .button {
    text-decoration:none;
    border: 2px solid #764abc;
    color: #764abc;
    padding: 10px 20px;
    border-radius: 25px;
    transition: all 1s;
    position: relative;
  }
</style>
<a href="#" class="button"> Hover me </a>

Second of all, we will create a pseudo-element for it

<style>
  .button::before {
    content:"",
    position:absolute;
    top:0;
    left:0;
    /* (X+Y) */
    width:100%;
    height:100%; 
    background-color: #764abc;
    transform: translateX(-100%);
  }
</style>

.btn:hover {
  color: #fff;
}
.btn:hover::before {
  transform:translateX(0);
}
.btn::before {
  transition:all 1s; /* for translateX */
}
.btn {
  transition:all 1s; /* for text color */
  overflow: hidden; /* for hidden the overflow pseduo-element */
}

3) CSS variables

CSS variables are one of the most exciting developments to come to CSS of all time. They're incredibly powerful, and they unlock lots of really effective workflows.

๐Ÿ’ก
It basically transforms the CSS meaningful values into application meaningful values. For example, we can have --warning:yellow;

Custom properties

The first thing to understand about CSS variables is that they function exactly like properties (like display, color, etc). You can name it whatever you want :)

strong {
  display: block;
  color: red;
  --favorite-food: tomato;
  --temperature: 18deg;
}
๐Ÿ’ก
the dashes (--) to differentiate them from built-in CSS properties

Access it using var( think of var in JS)

<style>

  main {
    font-size: 2rem;
    --favorite-food: tomato;
  }

  a {
    padding: 32px;
    background-color: var(--favorite-food);
  }

</style>

<main>
  <section>
    <a>Hello World</a>
  </section>
</main>

Not global

A common misconception is that CSS variables are "global." When we attach a CSS variable to an element, it's only available to that element and its children.

<style>
  a {
    --color: red;
  }

  main {
    color: var(--color); 
    <!-- can't access the color value -->
  }
</style>

<main>
  <section>
    <a>Hello World</a>
  </section>
</main>
๐Ÿ’ก
CSS variables are often hung on: root. The root is an alias for the html tag, the "root" of the HTML document. By attaching our CSS variable to the root, they're all inherited through the entire DOM element tree
:root {
  --color-primary: red;
  --color-secondary: green;
  --color-tertiary: blue;
}

Don't allow CSS variables to be inherited

What if we want that CSS variable to be available to it only, not any of its children?

<style>
  @property --text-color {
    syntax: '<color>';
    inherits: false;
    initial-value: black;
  }

  main {
    --text-color: deeppink;
    color: var(--text-color);
  }

  section {
    color: var(--text-color);
  }
</style>

<main>
  This text is just inside main.
  <section>
    This text is inside section.
  </section>
</main>

Used in combination with JS

It's a complex world, where in the FE we have many sort of compiler to make the experience of developers nicer

Compiler

If you've used a CSS preprocessor like Sass or Less, you might be thinking, โ€œSo what? We've had variables in preprocessors for years!"

The big difference is that CSS preprocessors can only be used to generate initial values. A .scss file will get compiled into a .css file, and the variables are resolved during that process before the code ever runs in the browser.

With CSS variables, however, the variable exists in the browser. This means we can dynamically change its value with JavaScript.

๐Ÿ’ก
Usually, we will dynamically change the value through style.setProperty(--color,"red");

๐Ÿ’ก
CSS variables are reactive, which means whenever we use JS to update the value, The UI will reflect those changes through CSS variables

Variable value in CSS

Just like in JS, we can store JS values in certain JS variables and then reuse them later. At this moment in time, we can use CSS to do the same thing

<style>
  body {
    // color name
    --pink-hue: 340deg;
    --blue-hue: 275deg;
    --intense: 100% 50%;
    // app name
    --color-primary: hsl(
      var(--pink-hue)
      var(--intense)
    );
    --color-secondary: hsl(
      var(--blue-hue)
      var(--intense)
    );
  }

  strong {
    color: var(--color-primary);
  }
  a {
    color: var(--color-secondary);
  }
</style>

<p>
  Hi <strong>Mario</strong>!
  <br />
  The princess is in <a href="">another castle</a>.
</p>

Color Theme in CSS

๐Ÿ’ก
We always have a problem when naming the color. Of course, CSS has come up with a bunch of named variables for color: red, orange, etc., but somehow it's too limited and often not what we want. We want to customize our color name and choose a different combination of colors. And thankfully, CSS variables have come to solve the issue for us
 :root {
    --gray:270deg;
    --color-gray-100: hsl(var(--gray) 20% 95%);
    --color-gray-300: hsl(var(--gray) 10% 75%);
    --color-gray-500: hsl(var(--gray) 5% 50%);
    --color-gray-700: hsl(var(--gray) 10% 30%);
    --color-gray-900: hsl(var(--gray) 15% 15%);

    --primary: 245deg 90%;  
    --color-primary: hsl(var(--primary) 50%);
    --color-primary-light: hsl(var(--primary) 70%);
    --color-primary-dark: hsl(var(--primary) 30%);
    --color-primary-alpha-300: hsl(var(--primary) 50% / 0.3);
    --color-primary-alpha-500: hsl(var(--primary) 50% / 0.5);
    --color-primary-alpha-700: hsl(var(--primary) 50% / 0.7);

    --secondary:350deg 95%;
    --color-secondary: hsl(var(--secondary) 50%);
    --color-secondary-light: hsl(var(--secondary) 70%);
    --color-secondary-dark: hsl(var(--secondary) 30%);
    --color-secondary-alpha-300: hsl(var(--secondary) 50% / 0.3);
    --color-secondary-alpha-500: hsl(var(--secondary) 50% / 0.5);
    --color-secondary-alpha-700: hsl(var(--secondary) 50% / 0.7);
  }

Update value in media-query

body {
  background-color:red;
} 
@media (prefers-color-scheme:dark){
  body {
   background-color:yellow;
  }
}
๐Ÿ’ก
With media queries, there are usually a lot of conditions under which we have to match our selector and change the value
--root {
  --color-background:red;
  @media (prefers-color-scheme:dark) {
     --color-background:yellow;
  }
}

body {
 color:var(--color-background);
}

4) The magic of calc

For almost a decade now, CSS has had the ability to do math!

.something {
  width: calc(100px + 24px);
  height: calc(50px + 25px * 4);
}

Why is it important? It can be useful when we want to calculate something dynamically in the land of CSS

.something {
  width: 14.286%;
  width: calc(100% / 7);
}
/* Mix units is also allowed */
.spill-outside {
  margin-left: -16px;
  margin-right: -16px;
  width: calc(100% + 16px * 2);
}

5) Layout

How does the clamp() function work?

Responsive design gives us the ability to do fancy things like scale a font in relation to the size of the viewport

But oftentimes, it can get too small or too big. We need better control of its scaling and clamp function in CSS, which is the answer to the problem

font-size:clamp(1.3rem , 2.6vw , 3rem );
/**
    clamp takes 3 argument (min , preferred value , max)
 => browsers will try to apply the preffered value and if it bellows
the min or above the max value -> browsers will fit to min or max

   Typical use-case is to set the preferred value to be the viewport
width => that's way when the view port gets bigger so the font

/**

6) Beyond viewport width and height

In CSS, vh and vw are units of measurement that are used to specify lengths as percentages of the viewport's height and width, respectively. While these units can be very useful for creating responsive and fluid layouts, there are some potential issues or challenges associated with using them

Better explaining with the picture I drew

100 vw problem?

100 vw is 100% width of the window; if we have a scroll bar on the right, it is 100% width.We will end up having another scrollbar on the vertical

100vh problem?

The problem with vh comes with mobile devices.100vh is literally 100% view high (should minus the tab bar)

Although I have 100vh of the viewport, I can't see the total view; it is covered up by the tab bar of the phone (natural for mobile devices)

๐Ÿ’ก
In most cases, we want 100vw or 100vh of the possible view for the users (minus the scrollbar and the tab bar of the phone )

The New CSS Units (lvw , lvh,svw, svh , dvw and dvh)

As of March 2022, new CSS viewport units svh, lvh, dvh, svw, lvw, and dvw are incoming as part of the efforts of Apple, Bocoup, Google, Igalia, Microsoft, and Mozilla to improve the web for developers; as part of a project called Interop 2022. Who had ever thought.


lvw and lvh stand for large viewport width and height

Unit lvw,lvh reflects the largest possible viewport height visible to the user.

In other words, the size when the browser UI is the smallest and the website content is the largest. lvh is essentially how the vh unit currently (at the time of this writing) acts.


svw and svh stand for small viewport width and height

Unit svw,svh reflects the smallest possible viewport height that is visible to the user. The smallest possible viewport height excludes all interface elements by the user agent.


dvw and dvh stand for dynamic viewport width and height

In addition to the large and small viewports, there's also a dynamic viewport that has dynamic consideration of the UA UI :

When the dynamic toolbars are expanded, the dynamic viewport is equal to the size of the small viewport

When the dynamic toolbars are retracted, the dynamic viewport is equal to the size of the large viewport

6) Flex vs grid

Flex

Grid

The algorithm of grid-auto-flow

The grid-auto-flow CSS property controls how the auto-placement algorithm works, specifying exactly how auto-placed items get flowed into the grid.

7) Position Layout

I've found an excellent article covering this topic

๐Ÿ’ก
Keep in mind that there are cases where we don't specify the top, left, right or bottom position or the inner content is bigger than the container

ZIndex

When we use itposition: fixed or absolute, we move the element out of the normal document workflow. Logically, it will create three layers (X, Y, and Z), and we have to decide which element is on top of the other. (ZIndex,StackingContext) will come together after this decision

๐Ÿ’ก
Keep in mind that the z-index must be used together with the position property (set to a different value) to have an effect

ZIndex + flex

Stacking context

ย