skip to Main Content

I am trying to create a modal which has frosted glass backdrop. Imagine an element that pops up when clicked.

So:
page -> element
Upon clicking on element:
Page -> frosted backdrop -> element

All the solutions I have read online require the use of filter. However, by CSS specifications, position: fixed does not work if filter or transform is used anywhere in the parent DOM hierarchy. That is because it creates a new context.

Is there any other to create a frosted glass backdrop?

Update

This the CSS specification which explicitly mentions that fixed will not work if the ancestor has transform, filter or perspective. In other words, if any item in the ancestry uses blur effect, this will not work.

fixed
The element is removed from the normal document flow, and no
space is created for the element in the page layout. It is positioned
relative to the initial containing block established by the viewport,
except when one of its ancestors has a transform, perspective, or
filter property set to something other than none (see the CSS
Transforms Spec), or the will-change property is set to transform, in
which case that ancestor behaves as the containing block. (Note that
there are browser inconsistencies with perspective and filter
contributing to containing block formation.) Its final position is
determined by the values of top, right, bottom, and left.

This value always creates a new stacking context. In printed
documents, the element is placed in the same position on every page.

https://developer.mozilla.org/en-US/docs/Web/CSS/position

In summary, all the solutions I have read online require the use of filter. I need one without (or a way to create a full screen backdrop without using
position: fixed

2

Answers


  1. For your frosted backdrop, just create a position-fixed element that fills the screen behind your modal dialog that uses the backdrop-filter property.

    Quoting from MDN’s page on backdrop-filter:

    The backdrop-filter CSS property lets you apply graphical effects such as blurring or color shifting to the area behind an element. Because it applies to everything behind the element, to see the effect you must make the element or its background at least partially transparent.

    Login or Signup to reply.
  2. There may be something wrong in the way you constructed your document with main content and modal, because testing below snippet on Chrome/Edge/Firefox shows nothing out of the ordinary and displays a backdrop-filter as advertised.

    The snippet shows four differently positioned elements

    • two inside a .wrapper, one positioned absolute and the other fixed.
    • two inside body, one positioned fixed and the other absolute.
    • All four are defined with a backdrop-filter.

    Each ‘modal’ contains

    • position: relative content which in turn has an ‘absolute’ positioned .modal-content::before as header.
    • All headers too have a backdrop-filter defined.

    As positioning and filters each create new stacking context, you now have an example using at least eight new stacking context, each with their own backdrop-filter being frosted glass over some content.

    I left out the onclick mechanism…

    :root { --bd-radius: 15px }
    
    .modal {
        width : 50%; height: 50%;
    
        /*******************************/
        /* Frosting and other graphics */
        /*******************************/
        -webkit-backdrop-filter: blur(3px);
        backdrop-filter: blur(3px);
    
        background-color: hsl(0, 0%, 100%, 0.15);
    
        border-radius: var(--bd-radius);
        border: 2px solid hsl(0, 0%, 100%, 0.3);
        box-shadow: 5px 5px 30px hsl(0, 0%, 0%, 0.3);
    }
    
    /* Four different locations */
    .m1 { inset: 10% auto auto 10% }
    .m2 { inset: 20% auto auto 20% }
    .m3 { inset: auto 20% 20% auto }
    .m4 { inset: auto 10% 10% auto }
    
    /* Distinguish between fixed/absolute */
    .absolute { position: absolute }
    .fixed    { position: fixed    }
    
    /* Another new stacking context */
    .modal-content {
        position: relative; width: 100%; height: 100%;
    }
    /* Positioning the modal header */
    .modal-content::before {
        position: absolute;
        top: 0; left: 0; width: 100%;
        content: 'header';
        
        -webkit-backdrop-filter: blur(5px);
        backdrop-filter: blur(5px);
    }
    
    /************************/
    /* just some demo stuff */
    /************************/
    
    *, ::before, ::after { box-sizing: border-box }
    
    html { /* responsive main fontsize using y=mx+b */
        font-size: calc(1.25vmin + 4px); /* (320,8)(1280,20) */
        font-weight: bold
    }
    
    body {
        margin: 0; background-color: DimGray; color: White;
        background-image: url("https://picsum.photos/id/26/1920/1080");
        background-size: cover;
        background-attachment: fixed;
        background-repeat: no-repeat;
    }
    
    .wrapper { width: 100%; min-height: 100vh }
    
    .content {
        width: 100%; min-height: 100vh;
        font-size: 4rem;
        color: Tomato;
    }
    
    .modal, .content, .modal-content {
        display: grid; place-items: center;
        text-align: center; word-break: break-word; hyphens: auto;
    }
    .modal {
        font-size: 2.5rem;
    
    }
    .modal-content::before {
        padding: 0.5rem 1rem;
        font-size: 2rem;
        color: hsl(0, 0%, 0%, 0.5);
    
        background-color: hsl(0, 0%, 0%, 0.3);
        border-radius: var(--bd-radius) var(--bd-radius) 0 0;
    }
    <div class="wrapper">
        <div class="content">some content in the background</div>
        <div class="modal m1 absolute">
            <div class="modal-content">
                <p>some modal</p>
            </div>
        </div>
        <div class="modal m2 fixed">
            <div class="modal-content">
                <p>some modal</p>
            </div>
        </div>
    </div>
    <div class="modal m3 fixed">
        <div class="modal-content">
            <p>some modal</p>
        </div>
    </div>
    <div class="modal m4 absolute">
        <div class="modal-content">
            <p>some modal</p>
        </div>
    </div>

    A codepen for instant fiddling: SO75550961, frosted glass

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search