简体   繁体   中英

How to use css backdrop-filter on text?

I'm trying to recreate this effect from Apples Aracde site: https://www.apple.com/apple-arcade/ Look at the "Play Extraordinary" text, it's got a backdrop filter applied and blurs the video behind it.

I can see they are using an SVG as an mask to clip the background, but I can't seem to do the same, the text comes out stretched or upside down.

Could anyone show me how to use text as an SVG mask to cut out the div/element with a backdrop filter on it?

Screenshot of the item in question: https://i.imgur.com/WHzO8Yj.png

As far as I know there's no way to directly apply the backdrop-filter:blur to a text element.



First solution: The Slowest One (Broken by chrome update)

  1. Create a container
  2. Apply a background to it (or to its::before pseudo-element)
  3. Use the filter:blur so that the container's background is blurred
  4. Apply a svg mask onto the svg element and then apply the same background to the container (or to its::before pseudo-element)

This way we have the blurried background on top that gets masked and the non-blurry version under it.

NOTE: applying the background to the container's::before pseudo element will allow you to modify the background without touching the svg mask (usefull if you need to flip the background to create more contrast but you can't modify the original image).

Second solution: The Fastest One

  1. Create a container
  2. Apply a background to it
  3. Create a svg element which will represent our "text"
  4. Apply the backdrop-filter:blur to the svg element
  5. Apply the svg-mask to the svg element

This way we have the effect we would have if the backdrop-filter: blur could be applied to text.
This one is the one which performs the best because it's the only method that doesn't require the svg element to duplicate the background (which would have to be repainted at every frame because of the background-attachment:fixed attribute).

Third solution: The Most Compatible One (Broken by chrome update)

(requires to have 2 copies of the background, one of which already blurred)

  1. Create a container
  2. Apply a background to it
  3. Create a svg element which will represent out "text"
  4. Apply the blurry version of the background to the svg element
  5. Apply the svg-mask to the svg element

Great. But the contrast is low...

Let's add a shadow then!

Applying the blur effect alone will give us a low contrast-ratio (hard to read text).
To counter this I applied a shadow to the svg:

  1. Create a svg element in the document
  2. Inside the <defs> tag create a filter with the <filter> tag and give it a unique id
  3. Inside the <filter> tag create a <feGaussianBlur> with a stdDeviation of your choice (4 and 5 are good initial numbers)
  4. Still inside the <filter> tag, create a <feComposite> with the out operator and in2 set to SourceGraphics
  5. To shape our shadow we'll use an <image> outside of the <defs> tag
  6. Set the url of the <image> 's filter attribute to the same id you gave to the <filter> tag (see point 2 above)
  7. Set the xlink:href attribute's value to the same one of your svg's path

This is the reference code:

<svg>
  <defs>
    <filter id = "trans-shadow">
      <feGaussianBlur stdDeviation = "5"/>
      <feComposite operator = "out" in2 = "SourceGraphic"/>
    </filter>
  </defs>
  <image filter = "url(#trans-shadow)" x = "0" y = "0" width = "100%" height = "100%" xlink:href = "./SVG.svg" />
</svg>

Live DEMO : https://cristiandavideconte.github.io/applyBackdropFilterBlurToText/
Source Code : https://github.com/CristianDavideConte/applyBackdropFilterBlurToText

I'll leave you a code snippet which contains the first 2 solutions (one is commented) so you can choose which one fits you better:

  <html>
  <head>
    <style>
        html,body {
            margin: 0;
            /* UNCOMMENT THIS PART TO TRY OUT THE NON-REVERSED VERSION
            background: url(https://wallpaperhd.wiki/wp-content/uploads/wallpapers-1920x1080-5ae1cd66635d3.jpg) 0 0;
            background-repeat: no-repeat;
            background-attachment: fixed;
            */
        }

        /* DELETE THE ::before TO TRY OUT THE NON-REVERSED VERSION */
        .container::before {
          content: "";
          z-index: -1;
          position: absolute;
          width: 100vw;
          height: 200vh;
          background: url(https://wallpaperhd.wiki/wp-content/uploads/wallpapers-1920x1080-5ae1cd66635d3.jpg) 0 0;
            background-repeat: no-repeat;
            background-attachment: fixed;
          transform: rotateY(180deg);
        }

        .container {
                width: 100vw;
                height: 200vh;
                display: flex;
                align-items: center;
        }

        .svg {
            position: absolute;
            z-index: 1;
            width: 100%;
            height: 100%;

            /* DELETE THIS 4 LINES TO TRY OUT THE NON-REVERSED VERSION */
            filter: blur(20px) saturate(180%);
            background: url(https://wallpaperhd.wiki/wp-content/uploads/wallpapers-1920x1080-5ae1cd66635d3.jpg);
            background-repeat: no-repeat;
            background-attachment: fixed;

            /* UNCOMMENT THIS PART TO TRY OUT THE NON-REVERSED VERSION
            backdrop-filter: blur(20px) saturate(180%);
            */

            /* Chrome, Safari and all webkit browsers */
            -webkit-mask-image: url(./SVG.svg);
            -webkit-mask-size: contain;
            -webkit-mask-position: center;
            -webkit-mask-repeat: no-repeat;
            -webkit-mask-border: url(./SVG.svg) 25;

            /* FIREFOX */
            mask-image: url(./SVG.svg);
            mask-size: contain;
            mask-position: center;
            mask-repeat: no-repeat;
            mask-border: url(./SVG.svg) 25;
        }
    </style>
</head>

<body>
    <section class = "container">
        <div class = "svg"></div>
    </section>
</body>
</html>

In order for this snippet to work you need the svg mask to be called SVG.svg and it has to be placed in the same folder as your html file.

And remember you cannot access an svg file for your mask's url from local storage , you need a server (node.js is fine).

Here you have 2 screenshots of the possible outcomes:

Method 3 - no shadows: Method 2 - with shadows:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM