Interesting CSS finds in the new Facebook design

I am curious. It’s always interesting for me to open the browser developer’s tools and to understand how any website I looked at is made. This material is my first story about such research. The fact is that I found some interesting examples of using CSS (at least they seemed interesting to me) that I wanted to talk about. We are talking about CSS finds in the new Facebook design. This design appeared relatively recently. I saw him a couple of weeks ago. At first, all the interface elements seemed unusually large to me, but I got used to them in just a few days. Here I will talk about all that interesting that I found in the design of Facebook.





Using SVG graphics in avatars



Avatars

SVG graphics are used for avatar images, such as profile photos, photos on user pages or in groups.

Here is the HTML code:

<svg role="none" style="height: 36px; width: 36px;">
  <mask id="avatar">
    <circle cx="18" cy="18" fill="white" r="18"></circle>
  </mask>
  <g mask="url(#avatar)">
    <image x="0" y="0" height="100%" preserveAspectRatio="xMidYMid slice" width="100%" xlink:href="avatar.jpg" style="height: 36px; width: 36px;"></image>
    <circle cx="18" cy="18" r="18"></circle>
  </g>
</svg>

When I saw this, I wondered why this approach was used. I have several answers to this question:

  • The avatar must have an inner frame that has a translucent black color (10%). This is to make light avatars look like round images. Moreover, even if these are completely white images.
  • You <img>cannot add an inner shadow ( box-shadow) to an HTML element using a keyword inset. SVG is used to solve this problem.
  • In order for the image to have a round shape, SVG elements <mask>and are used <image>.

As I said, the frames inside the avatar are very useful for bright images. Here is a layout that illustrates this idea.


Avatars The

inner frame is configured using the following CSS:

circle,
rect {
  stroke-width: 2;
  stroke: rgba(0, 0, 0, 0.1);
  fill: none;
}

If the image is square, the figure is used rect:

<svg role="none" style="height: 36px; width: 36px;">
  <mask id="avatar">
    <rect cy="18" fill="white" height="36" rx="8" ry="8" width="36" x="0" y="0"></rect>
  </mask>
  <g mask="url(#avatar)">
    <image x="0" y="0" height="100%" preserveAspectRatio="xMidYMid slice" width="100%" xlink:href="avatar.jpg" style="height: 36px; width: 36px;"></image>
    <rect cy="18" fill="white" height="36" rx="8" ry="8" width="36" x="0" y="0"></rect>
  </g>
</svg>

Interestingly, on the main page of the feed, avatars are created using the tag <img>and the element <div>used to configure the internal translucent frame:

<div class="avatar-wrapper>
    <img class="avatar" width="40" height="40" src="avatar.jpg" width="40" alt="">
    <div class="avatar-outline"></div>
</div>

Here are the styles for this HTML:

.avatar-wrapper {
    position: relative;
}

.avatar {
    display: block;
    border-radius: 50%;
}

.avatar-outline {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
    border-radius: 50%;
}

Since SVG in avatars is used only in some places, I can assume that the reason for the use <img>and <div>associated with a page size. If SVG graphics were used in avatars from the tape, this would lead to an increase in the amount of data loaded when scrolling through the tape.

Use as separators of <div> elements, not outer margins


I did not find those times when GIF images were used as separators of web page elements. But then I saw something resembling this technique. I think so, what I'm talking about can be called div separators.


<div> Elements Used as Separators

Let me clarify the above figure a bit. This is a fragment of the section that contains friend requests that appear on the home page. Before us is a certain grid with information about people. This grid should have a left outer indent. I usually add to the elements such as the border:margin-left: 16px. But Facebook did the same thing using the element<div>that separates the grid from the edge of the container element.

Why did designers do that? I have a few guesses:

  • Perhaps indentation for container elements cannot be added to the design system they created?
  • Maybe this is a React component that can be used anywhere by setting its width?

Why is not indentation used here? As for me, a CSS site (about 100 thousand lines), which is full of auxiliary classes, is able to accommodate another class that allows you to adjust the indentation of the desired element.

Using CSS Filters



Icons created using the <img> and <svg> elements

Take a look at these four icons. An icon with a plus sign and an arrow icon are created using an element<img>. And messenger icons and notifications - using SVG elements. The reasons for this mixture of technologies are unknown to me.

If you click on the last icon, the arrow will be repainted in blue. “How does color change here, because the arrow is an ordinary image?” I asked myself. Maybe when you hover over the icon, one image simply changes to another? No, it's not like that. I found out that a CSS filter is used to change the color of the icon on the icon:

.icon {
    filter: invert(39%) sepia(57%) saturate(200%) saturate(200%) saturate(200%) saturate(200%) saturate(200%) saturate(147.75%) hue-rotate(202deg) brightness(97%) contrast(96%)
}

And that, by the way, is the production code for facebook.com. This code seems very strange to me. Is it difficult to replace this element <img>with an SVG image and just change the color specified by the attribute fill?

The same is used when creating an icon for verified accounts.


Verified account icon

Something similar applies to links from the user profile:

.icon {
    filter: invert(59%) sepia(11%) saturate(200%) saturate(135%) hue-rotate(176deg) brightness(96%) contrast(94%);
}

This is how it looks


Links in the user profile

If you are interested in learning how to use an CSS filter to color an image in black with any color, take a look at this answer on Stack Overflow. There you can find a tool for creating CSS filters. Also, take a look at this tweet.

Using images to create shadows



A shadow created using background-image

The main window title has a shadow. It can be assumed that it was created using the CSS propertybox-shadow. But actually it is not. Here we used an element<div>with a background image that repeats along the axisx.

I uploaded the image used here, which allows me to take a closer look.


The image used to create the shadow

This is a 2x14 pixel image that, to create the shadow effect, is repeated many times. Not only the image, but also a special element is involved in the formation of the shadow effect<div>. Why was the shadow created this way?

A Facebook employee said that the image here was used for performance reasons. It is interesting that such a small shadow can lead to problems with the speed of the site.

When asked about how this problem was identified, he said that the shadow caused a serious drop in performance and unpleasant visual effects. So, when scrolling through a page on which there were many videos, some parts of the page appeared and disappeared.

Well, if the shadow causes such problems - I see nothing wrong with replacing it with the corresponding image.

Widespread use of CSS variables


I love the fact that Facebook designers use CSS variables. Judging by what I saw, :rootover 320 variables were added to the element . These variables are used in both light and dark themes of the site.

When a dark theme is enabled, a class is added to the HTML element __fb-dark-mode. Then it overrides all the variables declared in the element :root:

:root {
    /*    */
    -fds-active-icon#3578E5;
    --fds-attachment-footer-background#F2F3F5;
    --fds-blue-05#ECF3FF;
    --fds-blue-30#AAC9FF;
    --fds-blue-40#77A7FF;
}

.__fb-dark-mode:root, .__fb-dark-mode {
    /*     */
    --fds-active-icon:  black;
    --fds-attachment-footer-background:  black;
    --fds-blue-05:  black;
    --fds-blue-30:  black;
    --fds-blue-40:  black;
}

Here's a video that demonstrates what happens after switching to a dark topic. I advise you to watch it in full screen mode.

Using the line-clamp CSS property to trim multiline text



Signatures use multiline text trimming.

The sidebar has a list of links - such as those that lead to the user profile, to the latest materials, to the Memories section. I noticed that trimming multiline text is used here:

.element {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

These are built-in styles, which, in addition, vary depending on the browser.


Text Trimming Code in Chrome and Firefox

This CSS feature enjoys pretty good browser support. CanIUse reports that all leading browsers support this property (albeit with a prefix). Details on this property can be found here .

Using a div to create elements that respond to mouseover


Typically, the effects that accompany the mouse over an element are created using CSS. For example, if a certain button needs to be painted with a special shade of gray when you hover over it, just do the following:

.element:hover {
    background: #ccc;
}

However, it seems that on large sites such as Facebook, this approach is impractical. In the process of exploring the site, I drew attention to the element that is displayed only when you hover over it with a mouse (let's call it the “hover element”). This is its main task. Here is his style:

.hover-div {
    position: absolute;
    right: 0;
    left: 0;
    top: 0;
    bottom: 0;
    pointer-events: none;
    border-radius: 6px;
    inset: 4px 0px;
    background-color: var(--hover-overlay);
    transition-property: opacity;
    transition-timing-function: var(--fds-animation-fade-out);
    cursor: pointer;
}

The property value of opacitythis element is changed by JavaScript from 0to 1. I experimented with it and found out that it is used for many components. Below is a set of screenshots demonstrating the use of this element.


Using a hover element

I like the uniformity and simplicity provided by using the same effect for multiple elements. If this means something, it means that the design language used on the site is uniform, and that the system was carefully designed. Good job, Facebook!

Using the inset Property


We are talking about an abbreviated record of property values, implying an impact on the upper, right, lower, and left parts of an element. You can use the property insetas follows:

.element {
    inset: 4px 0;
    /*   : top: 4px, bottom: 4px, left: 0, right: 0 */
}

The property is insetconfigured for the above hover elements associated with some other elements. The style is embedded in HTML. I noticed its application to the component shown below.


Areas affected by the inset property are highlighted in blue.

When this material is written, the propertyinset supports only Firefox 66+.

Dir = "auto" attribute and CSS boolean properties 


On multilingual sites like Facebook, it’s sometimes difficult to predict exactly what the content will be. For example, the username in a component has an attribute dir=«auto». This means that the direction of the text will depend on the language. Say, when using English, the text will be displayed from left to right, and when using Arabic - from right to left.

Moreover, it should be noted that there is a built-in style that changes the direction of the text (there is a feeling that the attribute is dir=«auto»not enough). Here's what it looks like:

<div dir="auto" style="text-align: start;">محتوى بالعربية</div>

Notice that a style has been added to the element text-align: start. This uses a logical CSS property. The style, for LTR layouts, will look like text-align: right.

If you are interested in the features of RTL-stylization - take a look at this my material.

Dynamic background depending on the main photo



Background depending on the main photo

Have you noticed that a gradient and a color similar to the color of the main photo are used to design the background? This background is formed dynamically, it is based on the color of the photo. How it's done?

▍1. Getting dominant color


First you need to get the dominant (used more often than others) color of the main photo. After this color is found, a reduced version of the main photo is created, painted over only with this color.


Finding a dominant color

▍2. Adding a dominant color background



Background using dominant color

found Background uses dominant color found earlier. I, to make it clearer, highlighted the image displayed on the page as the main photo with a white frame.

▍3. Adding a gradient over the background


To add a gradient over the background, use the following CSS code:

.element {
    background-image: linear-gradient(to top, #FFFFFF, rgb(255, 255, 255), rgba(255,255,255,0.7), rgba(255,255,255,0.4), rgba(255,255,255,0));
}


Adding a gradient (light colors are used in the design)

In the event that dark colors are used in the design, the reverse gradient is used:

.element {
    background-image: linear-gradient(to top, #000, rgb(0, 0, 0), rgba(0,0,0,0.7), rgba(0,0,0,0.4), rgba(0,0,0,0));
}


Adding a gradient (dark colors are used in the design)

You can use this toolto find the dominant color of the image.

Multiple shadows



Shadows

I liked the approach Facebook developers used to create shadows for various elements like drop-down menus. Such a shadow creates the illusion of volume, which is much more realistic than the illusion achievable with a regular shadow.


Drop-down menus

Here is the CSS:

.element {
    box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(255, 255, 255, 0.5);
}

Here you may have a question about why here an inset shadow of white color is created with a transparency of 50%? The fact is that this is a shadow for the dark regime. Below is an enlarged fragment of the interface in which such a shadow is used.


An enlarged fragment of the interface with an inset shadow.

I like this reasonable solution.

Empty items for flexbox grids


I noticed that all grid layouts on the site are based on flexbox. Here is one example of such a layout that I found in the user's photos section.


Empty elements in the grid layout

Here is the CSS:

.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-items: space-between;
}

.item {
    width: 205px;
}

It all looks interesting, right? Using a value space-betweento adjust the placement of elements is risky. The layout will not look right if, for example, there are only three photos. An example of such a layout is shown below.


The danger of using space-between

How did the Facebook team deal with this problem? Very simple: there are four empty elements<div>, the width of which is equal to the width of the photo. Here is the HTML for this solution:

<div class="wrapper">
    <div class="item"><a href="#"><img src="photo.jpg"></a></div>
    <div class="item"><a href="#"><img src="photo.jpg"></a></div>
    <div class="item"><a href="#"><img src="photo.jpg"></a></div>
    <div class="item"><a href="#"><img src="photo.jpg"></a></div>
    <div class="empty"></div>
    <div class="empty"></div>
    <div class="empty"></div>
    <div class="empty"></div>
</div>

With this approach, such empty elements <div>play the role of artificial elements. They help maintain the same distance between the elements.

Using vertical media queries


I rarely see vertical media queries, so to speak, in the wild. I like the fact that Facebook developers used this query to reduce the width of the news feed on the home page:

@media (min-height: 700px) {
    .element {
        width: 584px;
    }
}

Summary


That's all. I was very interested in working on this article. Exploring the design of the Facebook site, I learned a lot. I hope you also found in my story something that seemed new and interesting to you.

Dear readers! Have you ever found anything interesting by analyzing the code of sites you visit?


All Articles