> All in One 586

Ads

Wednesday, June 3, 2026

Showers Late today!



With a high of F and a low of 51F. Currently, it's 61F and Clear outside.

Current wind speeds: 8 from the South

Pollen: 3

Sunrise: June 3, 2026 at 05:26PM

Sunset: June 4, 2026 at 08:13AM

UV index: 0

Humidity: 69%

via https://ift.tt/gVQJlIM

June 4, 2026 at 10:02AM

@function

The @function at-rule defines CSS custom functions. These custom functions are reusable blocks of CSS that can accept arguments, contain complex logic, and return values based on that logic. The feature is similar in nature to a more dynamic version of custom properties (CSS variables).

Note: There is also a @function at-rule in Sass which is similar in purpose but different in function to the native CSS @function. Be aware of this if Sass is part of your stack or when searching for resources as it is easy to conflate one with the other.

Syntax

The @function at-rule defines a custom function, using the following syntax:

@function --function-name(<function-parameter>#?) [returns <css-type>]? {
  <declaration-rule-list>
}

<function-parameter> = <custom-property-name> <css-type>? [ : <default-value> ]?

In other words, we define the function’s name as a dashed ident (--my-function), supply some condition we want to match (<function-parameter>), and say what sort of thing we want to return, say, a CSS[<length>] value. And, if that condition matches, we apply styles (<declaration-rule-list>).

Let’s dig deeper into what those things actually mean.

Arguments and Descriptors

There are a number of parts to the syntax for @function to handle different parts of the feature. It may all look very complex — and it is — but it’ll become clearer later when we look at some examples.

--function-token

A user-defined identifier that must start with two dashes (--), similar to the dashed-ident of custom properties. Just like custom properties, the name is case-sensitive. For example, --conversion and --Conversion would refer to different custom function definitions.

@function --progression()

<function-parameter> (optional)

An optional comma-separated list of inputs that can include:

  • --param-name: The name of the argument (must start with --).
  • <css-type> (optional): A keyword or type (e.g., <length>, <color>) that tells the function what sort of input or result it’s returning when it hits a matched condition.
  • <default-value> (optional): A fallback value that’s returned if the result is invalid, such as the argument is omitted during the function call. If you provide a default value, it must be valid to the aforementioned <css-type> (e.g. a <length> must default to a valid CSS length). It is separated from the rest of the parameter definition with a colon (:).
  • returns <css-type> (optional): Defines the expected output type of the function. This helps the browser validate logic before rendering. If a type isn’t specified then, anything will be valid (like writing returns type(*)).
  • <declaration-rule-list>: CSS declarations and at-rules that construct the function’s body and logic. It can include custom properties and the result descriptor — either at the root or nested within an at-rule.
@function --progression(--current <number>, --total <number>) returns <percentage> {
  result:
}

The result descriptor that defines what the custom function will return. If a custom function forgoes the result descriptor, it will always return guaranteed-invalid value, just like a broken custom property.

@function --progression(--current <number>, --total <number>) returns <percentage> {}

Basic Usage

For an example of the most basic function you could make, we have a function that calculates a provided value (e.g. 20px) in half (e.g. 10px), and returns returns it as a length unit (e.g. px):

@function --half(--size <length>) {
  result: calc(var(--size) / 2);
}

Here, we are ‘naming’ our function by setting the function-token to --half. We are then creating a function-parameter called --size, and setting the css-type to <length>, so that it will only accept length values. The result descriptor is set to calc(--size / 2), which uses the CSS Calculating Function to halve the value sourced from the size function-parameter.

We then use the function like so:

.container {
  margin-inline: --half(20px); /* This will resolve to 10px */
}

Type Checking

Just like when writing JavaScript or other languages, sometimes we want to ensure a function only accepts certain arguments. For example, what if we want to ensure that only numbers can be input and that only a percentage can be output?

@function --progression(--current <number>, --total <number>) returns <percentage> {
  result: calc(var(--current) / var(--total) * 100%);
}

.progress-bar {
  width: --progression(3, 5); /* Evaluates to 60% */
}

The <css-type> is enclosed in angle brackets in a manner identical to how you type-check a custom property via @property. If an argument does not match the declared type (e.g. <color>), the function call becomes invalid, which is very valuable for catching bugs early in large codebases.

You can use a <syntax-combinator> to allow multiple types by wrapping the types in type() and using | as a separator. For example, --alpha here allows both <number> and <percentage>:

@function --transparent(--color <color>, --alpha type(<number> | <percentage>));

Comma-Separated Lists

CSS uses commas to separate the inputs of a custom function, which begs the question: what if you wish to provide a list of values? To provide a list of values as one input rather than several separate inputs, you must first mark a function to expect a list.

To do this, you suffix the # character to the <css-type>. When calling the function, you then wrap the list of values in curly braces, which tells the browser to treat everything inside the braces as a single argument.

For instance:

/* Calculates the distance between the highest and lowest values in a list, plus another input */
@function --get-range(--list <length>#, --n <length>) {
  result: calc(max(var(--list)) - min(var(--list)) + var(--n));
}

div {
  /* Finds the difference between 10px and 100px, then adds 200px */
  padding-block: --get-range({10px, 100px, 50px, 25px}, 200px); /* 290px */
}

Constructs and the CSS Cascade

The result descriptor follows the rules of the CSS Cascade. That means you can declare multiple result values, and the last valid matching value will win, just like any other properties. As such, conditional group rules (@media, @container, @supports) and other functions, such as if(), provide a lot of additional possibilities.

In this case, we return a --suitable-font-size that defaults to 16px when the screen is less than 1000px pixels. If the screen is greater than 1000px then the “winning” style is what’s in the @media block.

@function --suitable-font-size() returns <length> {
  result: 16px;

  @media (width > 1000px) {
    result: 20px;
  }
}

body {
  font-size: --suitable-font-size();
}

Keep in mind that the last defined value always wins, so if you were to write the example below, the result would always be 16px, regardless of the media query being triggered.

@function --suitable-font-size() returns <length> {
  @media (width > 1000px) {
    result: 20px;
  }

  result: 16px;
}

The adherence to the established cascade also allows you to use custom properties within a function. These custom properties are locally scoped, so they are only accessible in your custom function and any custom function that references it and thus won’t unexpectedly leak out globally and interact with the rest of your CSS.

@function --spacing-scale(--multiplier) {
  --base-unit: 8px;
  result: calc(var(--base-unit) * var(--multiplier));
}

You can also use other custom functions within a custom function, essentially nesting one function within another. This allows for very clean code, where each section only does one job and functions can be widely reused.

@function --square(--n) {
  result: calc(var(--n) * var(--n));
}

@function --circle-area(--radius) {
  --pi: 3.14159;
  result: calc(var(--pi) * --square(var(--radius)));
}

.blob {
  width: calc(--circle-area(10) * 1px); /* 314.159px */
}

Defaults

Functions can handle multiple arguments and provide default values. The default value is defined by including it at the end of the function parameter, separated by a colon (:).

/* Define the function */
@function --brand-glass(--opacity <number>: 0.5) returns <color> {
  result: rgb(10 120 255 / var(--opacity));
}

/* Use the function */
.header {
  background: --brand-glass(); /* Defaults to 0.5 */
}

.header:hover {
  background: --brand-glass(0.8); /* Overrides to 0.8 */
}

No Side Effects

A CSS @function can only return a value; it cannot do anything else. For example, you cannot change a property inside of a function or use a function to generate multiple declarations. For such abilities, one must look to the proposed @mixin at-rule, which would provide functionality in this manner, allowing multiple lines of CSS properties and other complex logic.

Circular Dependencies

CSS is very strict about circular logic. If Function A calls Function B, and Function B calls Function A, the browser will catch this cyclic dependency and immediately mark both as invalid.

This also applies to CSS Custom Properties and referring to the custom function itself. If a function relies on a custom property or function that is itself calculated by that same function, the browser will end the calculation to prevent an infinite recursion.

Specification

The @function at-rule is defined in the CSS Custom Functions and Mixins Module Level 1 specification.

Browser Support

Unsupported browsers ignore @function, so fallback declarations and progressive enhancement strategies can be advantageous. You can use @supports to check if @function is supported in the user’s browser, like so:

@supports (at-rule(@function)) {
  /* ... */
}

Ironically, however, at time of writing, the @supports at-rule evaluation functionality doesn’t have full support across browsers (Chrome 148+ only), so you will need to check if it is supported in your case. You can see the discussion on this in CSS Drafts Issue #2463.

More Information


@function originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.



from CSS-Tricks https://ift.tt/fr6pMnS
via IFTTT

Tuesday, June 2, 2026

Partly Cloudy today!



With a high of F and a low of 55F. Currently, it's 64F and Clear outside.

Current wind speeds: 14 from the Southeast

Pollen: 3

Sunrise: June 2, 2026 at 05:26PM

Sunset: June 3, 2026 at 08:12AM

UV index: 0

Humidity: 72%

via https://ift.tt/vA64k8B

June 3, 2026 at 10:02AM

::search-text

The CSS ::search-text pseudo-element selects matching text from your browser’s “find in page” feature. For example, if you use your browser search to find “search-text” on this page, all instances of it will highlight. This pseudo-element lets us style the appearance of that highlight.

And a bonus! If there are multiple matches on the page, then ::search-text can be used with the :current pseudo-class to style the match that’s currently in focus.

You can “find in page” using the CTRL + F (for Windows) or "⌘F" (for Mac) keyboard shortcuts.

::search-text {
  background: oklch(87% 0.17 90) /* yellow */;
  color: black;
}

::search-text:current {
  background: oklch(62% 0.22 38) /* red */;
  color: white;
}

The CSS ::search-text pseudo-element is defined in the CSS Pseudo-Elements Module Level 4 specification.

Syntax

Pretty straightforward! Declare the pseudo-element and add your style rules:

<element-selector>::search-text{
  /* ... */
}

Usage

It’s typically declared by itself (::search-text), but can be appended to specific elements as well:

/* All text */
::search-text {}
html::search-text {} /* kind of redundant */
/* Specific element */
section::search-text {}
strong::search-text {}

We’re a little limited as far as what CSS properties we can declare in ::search-text. Here is what it supports:

And, yes, we can use it with custom properties, like:

:root {
  --color-blueberry: oklch(0.5458 0.1568 241.39);
}
::search-text {
  background-color: var(--color-blueberry);
}

Basic usage

With the ::search-text pseudo-element, we can style the matching text results from “Find in page”. Plus, if we want to style the currently focused matching text, then we attach the :current pseudo-class after ::search-text.

/* matches all searched text */
::search-text {
  color: green;
  background-color: white;
}
/* matches any header level 1 searched text */
h1::search-text {
  text-shadow: 12px 1px lightgrey;
  background-color: black;
  color: white;
}
/* the current searched header level 1 text */
h1::search-text:current {
  color: red;
  background: white;
}

Inheritance chain

All descendants always inherit styles applied through the highlight pseudo-elements. This way, individual properties set on highlights will cascade to all elements down the three. Take for example the following HTML:

<article>
  <h2>Highlight inheritance demo</h2>
  <p>Lorem ipsum dolor sit amet. <strong>Lorem</strong> appears again here. Another lorem appears here.
  </p>
</article>

We have an <article> container with two children: <h2> and <p>, the latter having a <strong> descendant of its own. We could style ::search-text in <article> with the following CSS, which would apply to all elements in <article>:

article::search-text {
  background: gold;
  color: black;
  text-decoration: underline;
}

Then, override the color property for only <p> and its descendants:

p::search-text {
  color: orange;
}

And do the same for text-decoration on the <strong> element:

strong::search-text {
  text-decoration: line-through;
}

When you search for “lorem”, the background of the first instance (inside <p> but outside <strong>) will inherit both the background and text-decoration values from <article>, while overriding its color value with its own orange.

Onto <strong>‘s “lorem” text, it will inherit the properties we set in its parent <p> and grandparent <article. So the color and background values are inherited directly from its parent, and since they haven’t been overridden, they stay. While we override the text-decoration value to line-through.

The key takeaway from this example is that properties for highlight elements are also individually inherited and overridden.

Targeting a text

In the demo below, we set text-decoration to underline to give any searched text a blue underline. This way, we can customize matching text while also leaving the default background color, which prevents people from getting confused about what’s going on.

::search-text {
  text-decoration: underline;
  text-decoration-color: oklch(65% 0.18 240);
  text-decoration-thickness: 0.22em;
  text-underline-offset: 0.15em;
}

Using :current

Using ::search-text with :current, we can style the currently focused match. For example, below we apply a light orange hue text decoration color with 0.3em thickness to the currently matched searched text:

::search-text:current {
  text-decoration-color: oklch(85% 0.22 38);
  text-decoration-thickness: 0.3em;
}

Some accessibility notes

For WCAG’s contrast standards, you need a contrast ratio of at least 4.5:1 between the text and background. Another piece of advice is not to change the search colors too much. In fact, this feature should be used sparingly since it may cause issues for users with cognitive issues, and as a core part of the browser, it can be generally confusing. My personal advice is to stick to only text-decoration and its associated properties since they are more subtle than the rest.

There’s also :past and :future

The :past and :future pseudo-classes are supposed to match the element entirely prior and entirely after a :current element, respectively.

However, the specification says:

The :past and :future pseudo-classes are reserved for analogous use in the future. Any unsupported combination of these pseudo-classes with ::search-text must be treated as invalid

Meaning, you can’t use :past:future or any other pseudo-class with the ::search-text pseudo-element. If your browser somehow works with them, kindly report the unexpected behavior by opening an issue with them.

Specification

The CSS ::search-text pseudo-element is defined in the CSS Pseudo-Elements Module Level 4 specification. This is still being tested and improved upon.

Browser support

Very wide support:


::search-text originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.



from CSS-Tricks https://ift.tt/xstnblw
via IFTTT

Monday, June 1, 2026

Partly Cloudy today!



With a high of F and a low of 53F. Currently, it's 60F and Clear outside.

Current wind speeds: 17 from the East

Pollen: 3

Sunrise: June 1, 2026 at 05:27PM

Sunset: June 2, 2026 at 08:12AM

UV index: 0

Humidity: 75%

via https://ift.tt/2RTg1Wx

June 2, 2026 at 10:02AM

Astro Markdown Component Utility for Any Framework

In the previous article, I spoke about the why and how to use a Markdown component in Astro.

Here, we’re going to expand on that and help you use Markdown everywhere — regardless of the framework you use. So, this works for React, Vue, and Svelte.

The entire process hinges on the Markdown utility I’ve built for Splendid Labz.

Why This Utility?

I hit a snag when using most Markdown libraries. I naturally write Markdown content like this:

<div>
  <div>
    <!-- prettier-ignore -->
    <Markdown>
      This is a paragraph

      This is a second paragraph
    </Markdown>
  </div>
</div>

But since most markdown libraries don’t account for whitespace indentation, they create an output with <pre> and <code> tags.

This is because Markdown treats the indentation beyond four spaces as a code block:

<div>
  <div>
    <pre><code>  This is a paragraph

      This is a second paragraph
    </code></pre>
  </div>
</div>

So you’re forced to strip all indentation and write it like this instead:

<div>
  <div>
    <!-- prettier-ignore -->
    <Markdown>
  This is a paragraph

  This is a second paragraph
    </Markdown>
  </div>
</div>

That’s hard to read and annoying to maintain.

My Markdown utility handles this whitespace issue and generates the correct HTML regardless of how your code is indented:

<div>
  <div>
    <p>This is a paragraph</p>
    <p>This is a second paragraph</p>
  </div>
</div>

Using This in Your Framework

It’s easy. You have to pass the Markdown text into the utility. If inline is true, then markdown will return an output without paragraph tags.

Here’s an example with Astro.

---
import { markdown } from '@splendidlabz/utils'
const { inline = false, content } = Astro.props
const slotContent = await Astro.slots.render('default')

// Process content
const html = markdown(content || slotContent, { inline })
---

<Fragment set:html={html} />

You can then use it like this:

<Markdown>
   <!-- Your content here -->
</Markdown>

Here’s another example for Svelte.

Svelte cannot read dynamic content from slots, so we can only pass it through a prop.

<script>
  import { markdown } from '@splendidlabz/utils'
  const { content, inline = false } = $props()
  const html = markdown(content, { inline })
</script>

<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html html}

And you can use it like this:

<Markdown content=`
  ### This is a header

  This is a paragraph
`/>

It’s rather simple to build the same for React and Vue so I’d leave that up to you.

Taking it Further

I’ve been building for the web — long enough to experience the frustration of doing the same things over and over again.

So I consolidated everything I use into a few simple libraries — like Splendid Utils, and a few others for layouts, Astro and Svelte components.

I write about all of them on my blog. Come by if you’re interested in better DX as you build your sites and apps!


Astro Markdown Component Utility for Any Framework originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.



from CSS-Tricks https://ift.tt/sdfOP15
via IFTTT

Sunday, May 31, 2026

Partly Cloudy today!



With a high of F and a low of 53F. Currently, it's 64F and Clear outside.

Current wind speeds: 9 from the East

Pollen: 3

Sunrise: May 31, 2026 at 05:27PM

Sunset: June 1, 2026 at 08:11AM

UV index: 0

Humidity: 39%

via https://ift.tt/6nz0sZe

June 1, 2026 at 10:02AM

Showers Late today!

With a high of F and a low of 51F. Currently, it's 61F and Clear outside. Current wind speeds: 8 from the South Pollen: 3 Sunris...