This is the 15th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

background

Let’s just look at two pictures

To summarize the style of glass mimicry, Michal Malewicz calls this UI design idea, which combines shadows, transparency, and blurry backgrounds, Glassmorphism because it gives people the texture of glass.

The glass mimicry background has a high strength of contrast, and the background blur effect makes the style more beautiful.

Vue components

First, we create Glassmorphism’s Components under Components

<template>
  <div class="Glassmorphism relative">
    <slot />
  </div>
</template>
Copy the code

The component is wrapped in a div, and the content center of the component is handed over to slot for distribution.

So let’s work with the Glassmorphism style.

First we define the properties of the component. Set the width, height and rounded corners of the component to be customizable.

const props = withDefaults( defineProps<{ width? : string | number height? : string | number radius? : string | number }>(), { width: '100%', height: '100%', radius: 12 } )Copy the code

Then we do a preliminary check on the attribute values.

const c_width = computed(() => addUnit(props.width))
const c_height = computed(() => addUnit(props.height))
const c_radius = computed(() => addUnit(props.radius))
Copy the code

You can see that we’re using addUnit to check our rules, so let’s see what addUnit says

export const isDef = (val: any) => val ! == undefined && val ! = = null if there is a value export / / const isNumeric (val: any) = > / = ^ \ d + (. \ \ d +)? $/.test(val) export const addUnit = (val: any) => {$/.test(val) => export const addUnit = (val: any) => { isDef(val)) { return undefined } val = String(val) return isNumeric(val) ? val + 'px' : val }Copy the code

It mainly consists of the above several utility functions

So we developed CSS.

<style lang="scss" scoped> $circlePath: calc(v-bind(c_radius) * 2); $radius: v-bind(c_radius); .Glassmorphism { width: v-bind(c_width); height: v-bind(c_height); border-radius: $radius; Background: Linear-gradient (to right Bottom, RGBA (255, 255, 255, 0.6), Rgba (255, 255, 255, 0.1)); backdrop-filter: blur(6px); Box-shadow: 0.8rem 0.8rem 1.3rem 0 Rgba (0, 0, 0, 0.15); &::before, &::after { position: absolute; content: ""; display: block; z-index: 2; border-radius: $radius; } &::before { width: calc(100% - v-bind(c_radius) * 2); height: 1px; top: 0; left: $radius; background: linear-gradient(to right, #fff, transparent); } &::after { width: 1px; height: calc(100% - v-bind(c_radius) * 2); top: $radius; left: 0; background: linear-gradient(to bottom, #fff, transparent); } } </style>Copy the code

Here we can actually see that the gradient we applied to the top and left border of the container is rounded so that the gradient is not completely removed. So we can add an auxiliary DOM for style tweaking

So are:

<div class="Glassmorphism relative">
    <div class="circle absolute top-0 left-0"></div>/ / new<slot />
</div>
Copy the code
.circle {
    width: $circlePath;
    height: $circlePath;
    border-radius: 50%;
    border: 1px solid #fff;
    clip: rect(0, $radius, $radius, 0);
    z-index: -1;
}
Copy the code

We clipped it to radius size and it was perfect.

Attached source code:

<template>
  <div class="Glassmorphism relative">
    <div class="circle absolute top-0 left-0"></div>
    <slot />
  </div>
</template>

<script lang="ts" setup>
import { addUnit } from '@/utils'
constprops = withDefaults( defineProps<{ width? : string | number height? : string | number radius? : string | number }>(), {width: '100%'.height: '100%'.radius: 12})const c_width = computed(() = > addUnit(props.width))
const c_height = computed(() = > addUnit(props.height))
const c_radius = computed(() = > addUnit(props.radius))
</script>

<style lang="scss" scoped>$circlePath: calc(v-bind(c_radius) * 2); $radius: v-bind(c_radius); .Glassmorphism { width: v-bind(c_width); height: v-bind(c_height); border-radius: $radius; Background: Linear-gradient (to right Bottom, RGBA (255, 255, 255, 0.6), Rgba (255, 255, 255, 0.1)); backdrop-filter: blur(6px); Box-shadow: 0.8rem 0.8rem 1.3rem 0 Rgba (0, 0, 0, 0.15); > .circle { width: $circlePath; height: $circlePath; border-radius: 50%; border: 1px solid #fff; clip: rect(0, $radius, $radius, 0); z-index: -1; } &::before, &::after { position: absolute; content: ""; display: block; z-index: 2; border-radius: $radius; } &::before { width: calc(100% - v-bind(c_radius) * 2); height: 1px; top: 0; left: $radius; background: linear-gradient(to right, #fff, transparent); } &::after { width: 1px; height: calc(100% - v-bind(c_radius) * 2); top: $radius; left: 0; background: linear-gradient(to bottom, #fff, transparent); }}</style>

Copy the code

You can copy it yourself, try it locally, and it works 100%, so I’m not going to run the project to show you.

And use with care: glass mimicry has a high degree of color contrast. Set the background to a warm gradient color for better results.