Fluent Design System presents a CSS-exclusive Acrylic Material trend

Exploring the advancements made in Microsoft's Fluent Design System and the integration of the new Acrylic Material across the Windows ecosystem, I was inspired to incorporate it into web layouts.

Referring to the specifications, an acrylic layer is composed as follows:

https://i.sstatic.net/Xlfx5.png

Thus, I attempted a CSS-only approach influenced by the layers depicted in the image provided below:

body {
  margin: 0;
  font: 1em/1.4 Sans-serif;
  background: url("https://cdn.pixabay.com/photo/2017/03/27/16/50/beach-2179624_1280.jpg") center center;
  background-size: 100vw auto;
}

main {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}
... (CSS code continues)
 
<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

The outcome closely resembles the specification and adapts responsively, but encounters a significant issue when stacking additional .acrylic divs – causing the background effect to cease.

The inquiry remains: Is there a more clever method to achieve Gaussian blur without replicating the body background for each child element? Alternatively, could there be a dynamic approach to determine its position?


2022 Update

At the time of my initial query, the backdrop-filter feature in CSS remained experimental, not yet enabled even in Chrome. Thus, I sought alternative solutions if feasible back then.

Enter the present day... Now universally activated in all browsers serving 0.5%+ users, resolving this previously complex task has now been simplified as indicated here.

Answer №1

UPDATED: 2022-05-07

Implemented backdrop-filter as the primary option due to improved browser support.


There are two possible approaches to tackle this issue...

  1. Utilize backdrop-filter on .acrylic for modern browsers

  2. Apply a blurred background on .acrylic for all browsers (including legacy ones)

1. Using backdrop-filter on .acrylic (For Modern Browsers)

main {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.acrylic {
  padding: 4em 6em;
  position: relative;
  background: rgba(0,0,0,0.5);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  margin: 7px;
}

body {
  background: url("https://images.unsplash.com/photo-1452723312111-3a7d0db0e024?w=700") center/cover;
  background-attachment: fixed;
  margin: 0;
  font: 1em/1.4 Sans-serif;
  color: #fff;
}
<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

2. Blurred Background on .acrylic (For Legacy Browsers)

We replicate the background on .acrylic elements as well, as reducing opacity alone will display content behind them rather than within them, which the blur filter does not cover...

An efficient way to calculate positions would be setting background-attachment: fixed for both the parent element (body) and the .acrylic elements, enabling multiple .acrylic elements as well ;)

Since we use the same background for parent and children, we can combine them together ;)

body, .acrylic::before {
  background: url("IMG_URL_HERE") center/cover;
  background-attachment: fixed;
}

Here is a functional code snippet ;) Adjusted opacity on .acrylic:after slightly to make the background more visible ;)

body {
  margin: 0;
  font: 1em/1.4 Sans-serif;
}

body, .acrylic::before {
  background: url("https://images.unsplash.com/photo-1452723312111-3a7d0db0e024?w=700") center/cover;
  background-attachment: fixed;
}

main {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.acrylic {
  padding: 4em 6em;
  position: relative;
  overflow: hidden;
  margin: 1em;
}

.acrylic::before {
  filter: blur(10px);
  content: "";
  position: absolute;
  left: -10px;
  top: -10px;
  width: calc(100% + 20px);
  height: calc(100% + 20px);
  z-index: -1;
}

.acrylic::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  opacity: 0.35;
  border: 1px solid #fff;
  background: #fff;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d...;
<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

<main>
  <div class="acrylic shadow">
    Acrylic material!
  </div>
</main>

Answer №2

Here's the solution to your problem, with some added enhancements.

The issue you were facing was due to a mismatch in background alignment between ::before and the body. By consolidating the CSS styles into one, I've simplified the code for easier editing.

To offer more control over opacity, I replaced #hex values with background:rgba(). This allows for better customization of opacity settings.

I've inserted comments within the CSS to outline the modifications made and provide clarity on the changes.

NOTE: Removing opacity from the ::after class enhances transparency and visibility of the noise texture. It appears that the semi-transparency of the noise texture causes this behavior. If you have further insight or explanations, please share. I introduced classes .nested and .parent for separate styling options. The third example excludes both classes for comparison.

Update: I noticed the exclusion blend filter mentioned in the spec was missing, so I've incorporated it as well. References are provided below the snippet.

CSS & HTML Snippet with 3 variations:

/* Consolidating background styles 
for seamless editing. Altering color 
from #333 to #fff increases filter effect */

html,
.acrylic:before {
  background: #333 url(https://source.unsplash.com/1600x900/?nature) 50% 100% fixed;
  background-size: cover;
}

body {
  margin: 0;
  font: 1em/1.4 Sans-serif;
}


/*spacing adjustments*/

div {
  margin: 5px;
}

main {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-flow: row wrap;
  height: 100vh;
}

.acrylic {
  padding: 4em 6em;
  position: relative;
  overflow: hidden;
}


/*Added browser compatibility for blur and included the exclusion blend filter as per specification*/

.acrylic::before {
  content: '';
  position: absolute;
  z-index: -1;
  height: 100%;
  top: 0;
  right: 0;
  left: 0;
  filter: blur(8px);
  -webkit-filter: blur(8px);
  -moz-filter: blur(8px);
  -o-filter: blur(8px);
  -ms-filter: blur(8px);
  background-blend-mode: exclusion;
}


/*changed color to rgba and removed opacity property*/

.acrylic::after {
  content: "";
  position: absolute;
  height: 100%;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  border: 1px solid #fff;
  background-image: url(data:image/png;base64,iVBORw...); /*base64 encoded image*/
}


/*Individual control over 
.nested and .parent opacity and color.*/

.parent::after {
  background-color: rgba(230, 240, 255, 0.50);
  opacity: 0.60;
}

.child::after {
  background-color: rgba(230, 240, 255, 0.30);
  opacity: 0.60;
}

.shadow {
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2), 0 1px 8px rgba(0, 0, 0, 0.4);
}
<body>
  <main>
    <div class="acrylic shadow parent">
      <div class="acrylic child">
        Acrylic material! <br />.parent on .child on
      </div>
    </div>
    <div class="acrylic shadow">
      <div class="acrylic child">
        Acrylic material! <br />.parent off .child on
      </div>
    </div>
    <div class="acrylic shadow">
      <div class="acrylic">
        Acrylic material! <br />.parent off .child off
      </div>
    </div>
  </main>
</body>

Sources and additional notes:

You can refer to CSS Tricks for creating a glass effect using filters here.

If you wish to apply the effect across multiple images, maintaining a blurred version alongside the original may become cumbersome. Responsive designs often require swapping images based on screen size, which could benefit from generating the effect directly from the source image rather than retaining duplicates.

For broader browser support, consider adding SVG filters as a fallback option. While not included in this snippet, you can incorporate them like this:

While new, CSS Filters may need vendor prefixes and lack universal adoption. On the other hand, SVG filters applied within CSS via HTML have wider compatibility. Utilizing SVG filters as a substitute for unsupported CSS filters offers an effective workaround.

Include inline SVG definitions referencing the filter ID via a url(). You could also encode the SVG filter as a data URL, though readability might suffer.

An example provided:

SVG:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <filter id="blur">
      <feGaussianBlur stdDeviation="5" />
    </filter>
  </defs>
</svg>

CSS

.glass::before {
    background-image: url('pelican.jpg');
    /* Fallback to SVG filters */
    filter: url('#blur');
    filter: blur(5px);
}

Explore further about CSS filter blends at https://css-tricks.com/basics-css-blend-modes

Answer №3

Updated for 2022

Summary: To achieve a blur effect, simply use backdrop-filter.

Initially, when I first posed the question, the backdrop-filter CSS functionality was still experimental and not yet supported in Chrome. Hence, I was seeking an alternative solution back then.

However, things have evolved since those early days. The backdrop-filter feature has been officially added to Chrome as of version 76, released on July 29th, 2019. This integration made it a viable choice for progressive enhancement scenarios. Similarly, after facing numerous delays, Firefox also rolled out support for this feature in their 103rd version on July 26th, 2022.

Considering that the cross-browser compatibility now hovers around 95%, with virtually all major browsers catering to over 0.5% of users supporting it, using backdrop-filter is undoubtedly the way to go:

/* Consolidating all acrylic layer effects into a single class */
.acrylic {
  /* Applying parent background + Gaussian blur */
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px); /* Also works in Safari */

  /* Adding exclusion blend for enhanced effect */
  background-blend-mode: exclusion;

  /* Introducing color overlay with reduced opacity */
  background: rgba(255, 255, 255, .6);

  /* Incorporating tiled noise texture for added depth */
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm ...
}

/* Additional styles provided for illustrative purposes... */
body {
  margin: 0;
  padding: 1.5em;
  font: 1em/1.4 Sans-serif;

  /* Centralizing background image definition within the body tag */
  background: url("https://cdn.pixabay.com/photo/2017/03/27/16/50/beach-2179624_1280.jpg") center center;
  background-size: 100vw auto;
}

main {
  display: grid;
  gap: 1.5rem;
  justify-content: center;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  grid-auto-rows: minmax(120px, auto);
}

div {
  padding: 1.5em;
  border-radius: 1px;
  border: 1px solid rgba(255, 255, 255, .2);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .1), 0 1px 8px rgba(0, 0, 0, .2);
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}
<main>
  <div class="acrylic">
    Acrylic material!
  </div>

  <div class="acrylic">
    <div class="acrylic">
      Nested acrylic effect!
    </div>
  </div>

  <div class="acrylic">
    Acrylic material!
  </div>

  <div class="acrylic">
    Acrylic material!
  </div>
</main>

Answer №4

Is there a more efficient method to apply gaussian blur without having to duplicate the body background for each child element?

Based on my knowledge, there is no better way in this scenario to achieve the desired effect, as both the background image and the filter need to be set on the same div.

Could there be a smarter approach to dynamically calculate its position?

From what I gather, the issue arises when additional div elements with the class .acrylic are added, causing duplication of the background image.

To resolve this, you can simply include background-attachment: fixed in the .acrylic::before div since you are using the same background image.

body {
  margin: 0;
  font: 1em/1.4 Sans-serif;
  background: url("http://www.wallpapers-web.com/data/out/191/5484624-sunset-wallpapers.jpg") center center;
  background-size: 100vw auto;
}

main {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.acrylic {
  padding: 4em 6em;
  position: relative;
  overflow: hidden;
}

.acrylic::before {
  background: url("http://www.wallpapers-web.com/data/out/191/5484624-sunset-wallpapers.jpg") center center;
  background-size: 100vw auto;
  background-attachment: fixed;
  filter: blur(10px);
  content: "";
  position: absolute;
  left: -10px;
  top: -10px;
  width: calc(100% + 20px);
  height: calc(100% + 20px);
  z-index: -1;
}

.acrylic::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  opacity: 0.65;
  border: 1px solid #fff;
  background: #fff;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOCssjsndEOSJCgsMdYOElqlaCPkoRAeGoSEb/idLS/myeduzREmJJFIptVLGIcq3bfNxeimutJRuJVTRdhOPMhc/YHEI61XTzQLMBLRlammncTpERchwkwCNrzmQtisWi…>; /* code shortened for brevity */

.shadow {
  border-radius: 1px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1), 0 1px 8px rgba(0, 0, 0, 0.2);
}
<main>
  <div class="acrylic shadow">Acrylic material!</div>
  <div class="acrylic shadow">Acrylic material!</div>
  <div class="acrylic shadow">Acrylic material!</div>
</main>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Adjusting text alignment to span the entire width with consistent automatic spacing

Imagine if I have a collection of N words. To illustrate, consider the following: Dog Peanut Oranges Lemon Disciplinary All these words vary in length. Let's assume there is a container with a variable width X (the container may adjust its size ac ...

Various formatting results between jsFiddle and my personal computer

I am currently designing an email template for myself, which includes a section with icons. I'm implementing this using SCSS. The icons are displayed using a div tag containing an img tag. While the icons themselves appear correctly, I encountered an ...

The height of my row decreases when I implement the z-index for a hover effect

Hey there! I'm currently working on creating a hover effect for my cards using Bootstrap and z-index. However, I've run into an issue where the z-index works fine when I hover over the cards, but the row loses its height. I tried adding a height ...

Implementing Ext JS Checkbox Inside a Row Editor

Does anyone have a solution for aligning the checkbox in a RowEditor to the center position? I am using the "triton" theme with Ext JS 6.0.0. The issue is that the checkbox is currently placed at the top of the row, while other fields like textfield or co ...

An element generated using a JavaScript loop is covering another element in the layout

I am facing an issue with positioning images within a div to a span. The problem arises as the images are overlapping each other and I am uncertain about how to properly place each image when it is added. Below is the code snippet: The CSS: <style ty ...

Using Three.js to showcase a <div> positioned above a canvas featuring a dynamic skybox

The process I used to create a skybox on a Three.js canvas is as follows: var urls = [ 'pos-x.jpg', 'neg-x.jpg', 'pos-y.jpg', 'neg-y.jpg', 'pos-z.jpg', 'neg-z.jpg' ] window.cubemap = ...

What is the best way to eliminate the space between the navbar and header?

Is there a way to remove the white gaps that appear before and after the header? I would appreciate any help in editing my code, as I am new to coding and have copied some of it from W3Schools. Here is a snippet of my code: <!DOCTYPE html PUBLIC " ...

I had hoped for the search results to be displayed in neat columns, but unfortunately only the text is formatted that

I am working on a WordPress plugin that displays search results. Here is the PHP code for the results: <?php /** * Search & Filter Pro * * Sample Results Template * * @package Search_Filter * @author Ross Morsali * @link http://w ...

What is the best way to make the Bootstrap navbar stay fixed at the top of the

I am currently experiencing an issue with the Bootstrap navbar while using version 5.0. Whenever the Bootstrap navbar expands, the content below it also moves down, which is not the desired behavior. I want the content to remain in place. I tried set ...

Resizing with Jquery results in sudden movement

I have used jQuery to create a set of buttons inside a <ul> element. I am now attempting to resize the <ul> by adding a handle to the top of it, but when I try to resize it, the element jumps as shown in the images below. What could be causing ...

Activate the capture property for the file selection based on the label that is selected

This is a form that consists of two labels: <form method="POST" action='/process' enctype="multipart/form-data"> <div> <label for="file" class="upload-button"><i class=" ...

The element remains stationary and does not shift positions

My form is not centralizing properly, it seems to be stuck to the left side of #wrapper. I've tried adjusting margin-top but it doesn't seem to affect its horizontal position at all. I've played around with different values for margin and ev ...

"Resolving an inconsistency problem with the Vary header in Htaccess

Could someone help me identify the issues in my htaccess code? I'm encountering errors: This response is negotiated, but doesn't have an appropriate Vary header. The resource doesn't send Vary consistently. ## add vary header <IfModule ...

Easy ways to align sprite images and text in the center

I am trying to utilize css sprites for my website. I have a basic image and some text that I would like to display together. My goal is to center the image on the page, and then vertically center the text next to it. As a newcomer to css, I am struggling t ...

Having trouble with applying a class in Gtk3 css?

MY ATTEMPT AND EXPLANATION: In my application, I have the following layout structure: GtkWindow GtkOverlay GtkBox GtkGrid GtkButton Even after trying to apply this CSS style: GtkButton{ background-color:blue; } T ...

The issue of the hamburger icon appearing as "X" seems to only affect certain mobile phones, while it displays correctly on desktops and most other mobile devices. The problem appears to be specifically

On certain mobile phones, the hamburger icon displays as an "X" instead of three horizontal lines. This issue specifically affects all XIAOMI mobile phones on various browsers, while most other devices and desktops show the correct hamburger icon. The < ...

Comparing the benefits of a 3-column flow layout to a traditional

I've been wondering about the popularity of 3 column flow layouts compared to using a table with 3 columns and one row. Can someone explain the advantages and disadvantages of using a flow layout versus a table layout for this scenario? Thank you ...

Issue with Bootstrap CSS: Default color change not functioning properly on Mobile devices, although it works correctly on Desktop

This is my first website project, you can check it out at www.craigdoesdata.de to see the issue I'm facing with CSS. I apologize if this question seems obvious or if it has already been addressed (I have spent a considerable amount of time searching f ...

Navigational menu utilizing hamburger icon in Bootsrap 4 framework

Currently, I am developing a website and have decided to utilize Bootstrap 4 for my project. My goal is to create a navbar layout that features a hamburger menu on the left side with additional navbar items positioned on the right. As the screen size decre ...

Achieve separation without resorting to the width hack

While I currently use the width hack 49% and border 1px to create a separator for a two-column layout, I am looking for a better way to achieve this. The issue with the current method is that it breaks the design when the viewport size changes. Below is a ...