Skip to content

Example of using squircle with css variables. #19

Open
@johannesmutter

Description

@johannesmutter

Hey there!

Here's an example CSS snippet on how to use squircles effectively with CSS variables (to increase performance and avoid repaints when using both a fill and outline).

Firstly, the .squircle class sets some basic styles such as background color, border color, and border width, using CSS variables. You would only need to adjust these variables when used in different contexts.

.squircle {
	--squircle-radius: var(--border-radius-large);
	--squircle-smooth: 0.7;
	--background-color: #EEE;
	--border-color: red;
	--border-hover-color: black;
	--border-width: 2px;
	background-color: var(--background-color);
}

The second part provides a fallback for browsers that don't support CSS Houdini & the paint api (identified by the absence of a .supports-paint-api class on the html element). It uses a standard border and border-radius.

html:not(.supports-paint-api) .squircle {
	border: var(--border-width) solid var(--border-color);
	border-radius: var(--squircle-radius);
}

If the browser supports Houdini (identified by the presence of a .supports-paint-api class on the html element), we set a mask image using the paint(squircle) function and provide padding.

html.supports-paint-api .squircle {
	--squircle-shape: paint(squircle);
	padding: var(--border-width);		
	mask-image: var(--squircle-shape);
	-webkit-mask-image: var(--squircle-shape);
	--squircle-outline: 0;
}

Next, we use a pseudo-element to display an outline for our squircle. We also set a transition effect for smoother visual changes.

html.supports-paint-api .squircle::before {
	content: "";
	display: block;
	position: absolute;
	z-index:0;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-color: var(--border-color);
	transition: all 0.2s ease;
	mask-image: var(--squircle-shape);
	-webkit-mask-image: var(--squircle-shape);
	--squircle-outline: var(--border-width);
}

We have also provided a style for when our squircle is in focus or when the user hovers over it (.squircle.highlightOnHover:hover::before, .squircle:focus-visible::before), changing the border color to the css variable --border-hover-color.

html.supports-paint-api .squircle.highlightOnHover:hover::before, 
html.supports-paint-api .squircle:focus-visible::before {
	background-color: var(--border-hover-color);
}

Finally, the last block of code applies some specific styles to the first child element of any element with the .squircle class.
For example if you have an image that's edge to edge and should be cropped you'll need this, since overflow: hidden doesn't work. The mask is scaled to 150% so it doesn't crop the bottom. Similarly when you would have an image or node with background color at the end, you would create this with > *:last-child

html.supports-paint-api .squircle > *:first-child {
	--squircle-outline: 0;
	--squircle-radius: 14px; 
	/* Unfortunately css calc doesn't work yet. 
	But if you're using SCSS you can replace the static value (in this example: 14px) with a formula:     
	calc ( var(--border-width) - var(--border-width) ) 
	*/
	mask-image: var(--squircle-shape);
	mask-size: 100% 150%;
	-webkit-mask-image: var(--squircle-shape);
	-webkit-mask-size: 100% 150%;
}

In a framework like Svelte or React you would import the squircle.min.js like below:

let isWorkletLoaded = false;
export default async function squircle() {
  if (typeof window !== "undefined" && "paintWorklet" in CSS) {
    if (!isWorkletLoaded) {
      await CSS.paintWorklet.addModule('/squircle.min.js');
      isWorkletLoaded = true;
      document.documentElement.classList.add('supports-paint-api');
    }
  }
}

This should provide you a starting point to start using squircles in your project.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions