<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>OddBird CSS Notebook</title>
  <subtitle>Notes towards the future of CSS, from Miriam Suzanne &amp; OddBird</subtitle>
  <id>https://css.oddbird.net/</id>
  <link href="https://css.oddbird.net/feed.xml" rel="self"/>
  <link href="https://css.oddbird.net/"/>
  <updated>2025-09-22T17:06:56Z</updated>
  <rights>© 2025 OddBird</rights>
  <icon>https://css.oddbird.net/favicon.svg</icon>
  <generator>Eleventy</generator>
  <author>
    <name>OddBird</name>
    <email>birds@oddbird.net</email>
  </author><entry>
    <link href="https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/"/>
    <updated>2025-09-22T17:06:56Z</updated>
    <id>https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/</id><title>
        Changes to: CSS Overflow - Broad Research
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Remove and re-link Chrome’s carousel proposal as tangential to the goals of this&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;document&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/overflow/explainer/&quot;&gt;
          CSS Overflow - Broad Research »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Remove and re-link Chrome’s carousel proposal as tangential to the goals of this&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;document&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/overflow/explainer/&quot;&gt;
          CSS Overflow - Broad Research »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;details data-alert=&quot;warn&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;This is not a carousel explainer:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;Chrome asked me to pursue
a proposal for &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; carousels,
but I only agreed to research a broader
set of issues around overflow.
I created this explainer to explore
paged overflow generally in screen&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;media.&lt;/p&gt;
&lt;p&gt;Once that research was complete,
Chrome began to contribute
carousel-specific proposals here –
and link this document as The Carousel Explainer.
I’ve removed that content,
since it’s not a proposal I’m involved with,
and not the goal of this&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;document.&lt;/p&gt;
&lt;p&gt;For their proposal,&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/flackr/carousel/&quot;&gt;Rob’s Carousel Explainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9745&quot;&gt;Related &lt;span class=&quot;caps&quot;&gt;CSSWG&lt;/span&gt; discussion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;h2 id=&quot;participate&quot;&gt;Participate &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#participate&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Anyone can comment on,
file issues against,
or contribute to this explainer
on GitHub:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/oddbird/css-sandbox/blob/main/src/overflow/explainer.md&quot;&gt;This document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/oddbird/css-sandbox/issues&quot;&gt;Issue tracker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also rely heavily
on some existing proposals
discussed in the CSS Working Group
issue tracker:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1183&quot;&gt;[css-grid] Flow multiple elements together into same grid area&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/4416&quot;&gt;[css-grid] grid area as element&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/499&quot;&gt;[css-grid] Decorative grid-cell pseudo-elements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/6017&quot;&gt;[css-multicol-2][css-scroll-snap] Snapping to column boxes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#introduction&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Managing layout and design on the web
requires careful control of ‘overflow’ –
allowing content to be hidden
when it’s not needed,
but accessibly discovered and revealed
when necessary.&lt;/p&gt;
&lt;p&gt;There are many overlapping
user-interface design patterns
that can be used –
from standard continuous scrolling,
to scroll-snapping,
slideshows, carousels,
accordions, tabs,
and various hybrid approaches.
The lines between these patterns
are often somewhat blurry:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS currently supports several overflow values,
but the only built-in overflow-access interface
is the continuous scrolling container.
That can be extended with features
such as scroll-animation,
scroll-behavior, scroll-snapping,
and so on.&lt;/li&gt;
&lt;li&gt;At the other end of a spectrum,
most tab and accordion patterns
are highly structured &amp;amp; sectioned overflow.
Each section has an interactive label
that can be used to show or hide
the section contents (often one-at-a-time).&lt;/li&gt;
&lt;li&gt;In-between those two extremes,
there are a wide range of patterns
that get referred to as ‘carousels’.
These are not limited to the (problematic)
infinite-auto-advancing home-page widgets,
but range from video-streaming
media selection,
to slide shows,
and e-commerce product-image viewers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There have been many attempts
over the years
to define new tab or carousel components –
but they are often held up by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The complexity of
use-case mixing and matching
patterns from scrollers, carousels,
tabs, and accordions&lt;/li&gt;
&lt;li&gt;The need to work around many
underlying features
that are missing from the web platform&lt;/li&gt;
&lt;li&gt;The fact that ‘overflow’
is a presentational concern
tightly coupled with device/media/size conditions
(and therefor part of CSS),
but also requires interactive controls
generally left to HTML components or JavaScript.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#goals&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The goal of this explainer
is not to propose yet another component,
or provide a one-size-fits-all solution
for all overflowing UI –
but to consider some baseline improvements to CSS overflow
that could help authors
flesh out the details of each pattern more elegantly,
consistently, and accessibly.
This could also help form the scaffolding
for future components, as needed.&lt;/p&gt;
&lt;p&gt;In some cases,
we’re able to propose a path forward –
and in other cases,
we simply document the problem
and some of the tradeoffs
with different approaches.&lt;/p&gt;
&lt;h3 id=&quot;overlapping-patterns&quot;&gt;Overlapping patterns &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#overlapping-patterns&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The patterns we’re looking at
fall along a continuum
of scrolled and paged overflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On one end,
media-scroller carousels
(like the Netflix video selection interface)
are similar to horizontal overflow
with scroll-snapping,
and the occasional use of ‘next/previous’ navigation
that is sometimes linked to items
and sometimes to ‘pages’ of overflow.&lt;/li&gt;
&lt;li&gt;Slide-show style carousels
often add small ‘scroll-markers’ (like dots)
that represent either
the individual items listed,
or the viewable pages
(if multiple items appear at once).&lt;/li&gt;
&lt;li&gt;Product-image carousels will often
replace the dots with thumbnail image scroll-markers,
and only show one item per ‘page’.
In this case general mouse scrolling
(and visible scroll-bars)
are often removed in favor of tab controls,
while sometimes leaving gesture-based scrolling intact.&lt;/li&gt;
&lt;li&gt;Tabs are similar,
but may often removing scroll-controls entirely.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rather than thinking of these
as distinct patterns,
we want to understand the underlying set of controls
that are combined to create
any given variation.
Primarily: paged overflow
and interactive scroll markers
in a variety of forms.&lt;/p&gt;
&lt;h3 id=&quot;overflow-changes-based-on-context&quot;&gt;Overflow changes based on context &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#overflow-changes-based-on-context&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While HTML, CSS, and JS
often have distinct and separate ‘concerns’ –
semantics, presentation, and interaction –
overflow falls into a middle ground
that can be hard to break apart.
Content that overflows on one device,
or at a particular screen size,
may not need to overflow in other situations.
That’s a presentational concern,
rather than a semantic one,
and often needs to be handled using media queries.&lt;/p&gt;
&lt;p&gt;However,
semantics do play a clear role in
what patterns make sense
(the difference between a carousel and tabs
often comes down to how content is sectioned),
and different types of ‘overflow’ require
different interactions.
Any solutions provided here
have to account for changes in overflow
based on device/media/container context –
and help authors access the proper interactions
and accessible roles
for each type of overflow.&lt;/p&gt;
&lt;h2 id=&quot;non-goals&quot;&gt;Non-goals &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#non-goals&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;application-level-tabs&quot;&gt;Application-Level Tabs &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#application-level-tabs&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The ‘tabs’ interface pattern
has two common
and somewhat distinct use-cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Managing display of sectioned content
within a single document&lt;/li&gt;
&lt;li&gt;Managing display of multiple documents
within an application&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The former can be seen
as a form of ‘content overflow’
covered by by this proposal.
When searching within a document,
users would expect content in hidden sections
to be ‘discoverable’.
On the other hand,
application level tabs
(such as in a browser or text-editor)
represent distinct documents
rather than ‘overflow’.
Users would not expect a search in one document
to reveal content in another tab.&lt;/p&gt;
&lt;p&gt;This proposal is specific to
handling content overflow presentation in HTML and CSS,
rather than providing a generic solution
to the ‘tabs’ interface design pattern.&lt;/p&gt;
&lt;h3 id=&quot;auto-advancing--cyclic-home-page-carousels&quot;&gt;Auto-advancing &amp;amp; Cyclic Home Page Carousels &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#auto-advancing--cyclic-home-page-carousels&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The term ‘carousel’
has a strong negative connotation
in web design circles,
thanks to the poor user-experience
of home page carousels
used to display an endless cycle of
‘featured’ content.&lt;/p&gt;
&lt;p&gt;Readers rarely interact with this pattern,
and generally don’t see content
beyond the first page of the carousel,
unless forced by auto-advancement,
which causes a whole new list
of accessibility and usability issues.&lt;/p&gt;
&lt;p&gt;While that makes us hesitant
to use the term ‘carousel’ here,
there are a range of much more essential use-cases
that fall under the term –
and it’s helpful to understand
the somewhat fluid and overlapping nature of
scroll/carousel/tab/accordion patterns.&lt;/p&gt;
&lt;h3 id=&quot;virtual-lists&quot;&gt;Virtual lists &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#virtual-lists&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Virtual lists are tightly related to overflow,
but outside the scope of this document.&lt;/p&gt;
&lt;h2 id=&quot;possible-solutions&quot;&gt;Possible solutions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#possible-solutions&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Rather than proposing a single
complete solution to these fluid ux patterns,
we think it would be useful to address
the core HTML/CSS
layout and overflow issues
that make such an element difficult to implement.
This should provide a stepping-stone
for both authors and browser vendors
to explore and develop more narrowly defined
web-components or HTML elements
where they make sense.&lt;/p&gt;
&lt;p&gt;There has already been
some significant progress
along these lines.
The &lt;code&gt;scroll-snap&lt;/code&gt; properties,
scroll-linked animations,
and size container queries
all help authors better address overflow.
Below, we’ll explore some of the features
that are still missing or difficult
for authors to get right.&lt;/p&gt;
&lt;h3 id=&quot;paged-overflow-in-the-browser&quot;&gt;Paged overflow, in the browser &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#paged-overflow-in-the-browser&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Simple carousels (or ‘media-scrollers’)
are often built with scrollable overflow
and scroll-snap targets.
What makes it a ‘carousel’ is the addition
of ‘paged’ navigation options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;next/previous page arrows&lt;/li&gt;
&lt;li&gt;page markers (often dots)
to show the number of pages
and current active position&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Paged overflow isn’t a new idea in CSS.
While implementations have not always been
complete or consistent,
paged overflow is already well-defined for print,
and has a number of
&lt;a href=&quot;https://rachelandrew.co.uk/archives/2020/04/07/making-things-better/&quot;&gt;other use-cases&lt;/a&gt;
if it were available in the browser.&lt;/p&gt;
&lt;p&gt;Establishing paged overflow on an element
would generate &lt;code&gt;::page&lt;/code&gt; pseudo-element
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Fragmentainer&quot;&gt;fragmentainers&lt;/a&gt;
for descendant elements &amp;amp; content to flow through.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pages are created as-needed
based on the amount of content,
and the size available to each page.&lt;/li&gt;
&lt;li&gt;by default, a page could be the size
of the containing box (not including overflow),
so that scrolling the view 100%
would bring a new ‘page’ fully into view.&lt;/li&gt;
&lt;li&gt;Pages could be resized,
which would impact how much content
fits in a given page,
how many pages are visible without scrolling,
and how many pages are needed
for the flow of content.&lt;/li&gt;
&lt;li&gt;Individual pages could be targeted
using a syntax similar to &lt;code&gt;nth-child&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s not immediately clear
what syntax would be best
for invoking this sort of paged overflow.
While this behavior is related to both &lt;code&gt;overflow&lt;/code&gt;
and (in some ways) &lt;code&gt;display&lt;/code&gt;,
neither property seems like a particularly good fit.&lt;/p&gt;
&lt;p&gt;Paged use-cases (e.g. carousels)
might involve scrolling between pages,
while others (e.g. multicol wrapping) may not.
So pagination is not necessarily alternative to scrolled overflow.
Even if paged overflow had an &lt;code&gt;auto&lt;/code&gt;-like scroll behavior,
to allow scrolling and non-scrolling pages,
single-axis paged overflow(&lt;code&gt;-x&lt;/code&gt;/&lt;code&gt;-y&lt;/code&gt;) doesn’t make much sense.&lt;/p&gt;
&lt;p&gt;Authors will also need a mechanism
for handling the layout of
elements within pages
(and the layout of the pages themselves) –
both of which require display values.
It’s possible the pagination and layout controls
could be combined in a single property
(e.g. &lt;code&gt;display: paged grid&lt;/code&gt;)
if it makes sense for them to cascade together.
Since display is a shorthand for
inside and outside values,
pagination would either need to be added
to one of those properties
or a third new display sub-property.&lt;/p&gt;
&lt;h3 id=&quot;styling-paged-overflow&quot;&gt;Styling paged overflow &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#styling-paged-overflow&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As mentioned above,
authors will need a way to provide
&lt;code&gt;display&lt;/code&gt; values for both&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the layout of &lt;code&gt;::page&lt;/code&gt; elements themselves&lt;/li&gt;
&lt;li&gt;the layout of child contents
flowing through those pages&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I would expect the overflowing/paginated parent element
to handle the layout of pages,
in which case
a new (&lt;code&gt;::page-contents&lt;/code&gt;?) could be used
for the layout of content flowing through pages
(or vice versa).
An additional wrapping pseudo-element
like this might only support a limited subset of
CSS properties or pseudo-classes.&lt;/p&gt;
&lt;p&gt;In some cases,
an author would style all &lt;code&gt;::page&lt;/code&gt; elements,
but it would often be useful
to target specific pages
with e.g. &lt;code&gt;::page:nth-child(even)&lt;/code&gt;
(or &lt;code&gt;::page(even)&lt;/code&gt;).
However,
there might be recursion issues
with other combinations,
such as &lt;code&gt;::page:nth-last-child(even)&lt;/code&gt;
or &lt;code&gt;::page:focus-within&lt;/code&gt;,
if the styles applied
could change the number of pages
or placement of content in those pages.&lt;/p&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Note:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;Could these pseudo-classes be used for paged
(e.g. print) media as&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;well?&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;h3 id=&quot;page-navigation--pagination&quot;&gt;Page navigation / pagination &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#page-navigation--pagination&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One of the design patterns
often associated with a ‘carousel’ component
is the use of ‘dots’ for
page-based navigation.
Rather than (or in addition to)
a continuous scrollbar,
readers can select the page
they want to move to.
These ‘scroll markers’ or ‘pagination markers’
are much like list markers –
often taking the form of dots/bullets,
but occasionally styled as counters,
or even thumbnails and other content.&lt;/p&gt;
&lt;p&gt;Sometimes those page-access markers
represent individual items in a list.
This per-item marking
has a large overlap with ‘tabs’ –
a line that blurs in
‘product-image’ carousels for example.
Where’s the line between
a carousel-marker with an image thumbnail,
and a section tab with a text label?&lt;/p&gt;
&lt;p&gt;In general,
item-based markers
can be provided by authors in the markup,
along with the items they mark.
In that case,
the main concerns are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keeping the markers
inline with the items they mark,
vs creating a distinct table-of-contents
before/after the flow of items/pages&lt;/li&gt;
&lt;li&gt;Managing the link between markers
and the content they mark&lt;/li&gt;
&lt;li&gt;Maintaining the current state
of active content and markers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll explore
some of those issues more below.&lt;/p&gt;
&lt;p&gt;However, many scroll markers represent
the abstract ‘pages’ generated by
a flow of content –
where the number of markers may change
based on the size of a container –
or arbitrary scroll-snap points
that combine items and pages.
In those situations,
a marker would need to be generated
either using JavaScript,
or (ideally) by the browser.&lt;/p&gt;
&lt;p&gt;Una Kravets and Adam Argyle
have explored this in an early draft
&lt;a href=&quot;https://github.com/argyleink/ScrollSnapExplainers/tree/main/css-scroll-marker&quot;&gt;&lt;code&gt;::scroll-marker&lt;/code&gt; explainer&lt;/a&gt;.
In their proposal,
markers can be generated
by setting a &lt;code&gt;scroll-display&lt;/code&gt; property
to one of &lt;code&gt;bar&lt;/code&gt; (the default),
&lt;code&gt;auto&lt;/code&gt;, or &lt;code&gt;marker&lt;/code&gt;
on the scrolling parent.
This leaves a number of interesting questions
open for consideration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Would we need a way to request markers generated
per-item, per-page, or per-snap-target?
Can those options be combined?&lt;/li&gt;
&lt;li&gt;Can the &lt;code&gt;scroll-display&lt;/code&gt;
can be set differently for inline/block axis?&lt;/li&gt;
&lt;li&gt;Can values be combined to show both
a continuous-scroll bar and also scroll markers?&lt;/li&gt;
&lt;li&gt;Do previous/next arrows fall into a similar category?
While they are simpler for authors to provide in-markup,
they require a fair amount of state-management
to get right.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;interactive-state-managing-generated-content&quot;&gt;Interactive, state-managing, generated content? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#interactive-state-managing-generated-content&quot;&gt;¶&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;One of the most difficult aspects
in building web carousels, slideshows, and tabs
is proper ‘wiring’ for the interactive navigation
(dots, tabs, prev/next) –
with proper accessibility and keyboard interaction,
along with scroll-position and active-state management.
This is especially true
when the ‘targets’ of that navigation
are based on fluid overflow
rather than specific DOM elements.&lt;/p&gt;
&lt;p&gt;This is the primary reason
that authors would prefer a
built-in web platform solution,
but it also raises big questions
about using ‘generated content’
for interactive controls.&lt;/p&gt;
&lt;p&gt;The generated markers
would also need to track and expose
the current active state -
providing a way to style the active marker.&lt;/p&gt;
&lt;h3 id=&quot;per-item-markers--tabs&quot;&gt;Per-item markers &amp;amp; tabs &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#per-item-markers--tabs&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In more tab-like cases,
where a predictable number of markers are needed –
e.g. one marker per list-item –
they could be provided in markup.&lt;/p&gt;
&lt;p&gt;This has several advantages,
since it gives authors more control,
and doesn’t rely on interactive pseudo-elements.
However, it still comes with
it’s own set of issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do we need a new element or attribute for assigning
scroll-marker behavior?
Or do authors have to do
all the interaction/state-management manually?&lt;/li&gt;
&lt;li&gt;Is there a way for authors to keep the marker markup inline,
and still ‘hoist’ the element into a parent grid context?&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tabs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;marker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;tab label&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;panel&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;tab panel&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  …&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tabs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;layout-of-scroll-markers--tabs&quot;&gt;Layout of scroll-markers / tabs &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#layout-of-scroll-markers--tabs&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1183&quot;&gt;[css-grid] Flow multiple elements together into same grid area&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/4416&quot;&gt;[css-grid] grid area as element&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/499&quot;&gt;[css-grid] Decorative grid-cell pseudo-elements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;key-scenarios&quot;&gt;Key scenarios &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#key-scenarios&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[TBD]&lt;/p&gt;
&lt;h2 id=&quot;detailed-design-discussion--alternatives&quot;&gt;Detailed design discussion &amp;amp; alternatives &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#detailed-design-discussion--alternatives&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[TBD]&lt;/p&gt;
&lt;h2 id=&quot;prior-art--context&quot;&gt;Prior Art &amp;amp; Context &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#prior-art--context&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2021/10/native-html-tabs/&quot;&gt;spicy-sections&lt;/a&gt;
from OpenUI&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/argyleink/ScrollSnapExplainers/tree/main/css-scroll-marker&quot;&gt;&lt;code&gt;::scroll-marker&lt;/code&gt; proposal&lt;/a&gt; from Una Kravets &amp;amp; Adam Argyle&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;stakeholder-feedback--opposition&quot;&gt;Stakeholder Feedback / Opposition &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#stakeholder-feedback--opposition&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;[TBD]&lt;/p&gt;
&lt;h2 id=&quot;references--acknowledgements&quot;&gt;References &amp;amp; Acknowledgements &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/overflow/explainer/2025-09-22t170656000z/#references--acknowledgements&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Much of this work is based on
the research and proposals
compiled by others:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Robert Flack&lt;/li&gt;
&lt;li&gt;Nicole Sullivan&lt;/li&gt;
&lt;li&gt;Rachel Andrew&lt;/li&gt;
&lt;li&gt;Una Kravets&lt;/li&gt;
&lt;li&gt;Adam Argyle&lt;/li&gt;
&lt;li&gt;Brian Kardell,
Dave Rupert,
Jon Neal,
Sarah Higley,
Scott O’Hara,
and others
in the OpenUI Community Group.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/scope/parent-selector/"/>
    <updated>2025-07-02T00:00:00Z</updated>
    <id>https://css.oddbird.net/scope/parent-selector/</id><title>
        New page: Defining the `&amp;` selector in a `@scope` rule
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/scope/parent-selector/&quot;&gt;
          Defining the `&amp;amp;` selector in a `@scope` rule »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/scope/parent-selector/&quot;&gt;
          Defining the `&amp;amp;` selector in a `@scope` rule »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;TL;DR
we &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9740#issuecomment-3028423633&quot;&gt;resolved&lt;/a&gt;
during the scope breakout session
that &lt;code&gt;&amp;amp;&lt;/code&gt; nested directly inside &lt;code&gt;@scope&lt;/code&gt;
should refer to the implicit &lt;code&gt;:where(:scope)&lt;/code&gt; selector
that is prepended on
declarations and scoped selectors
by default.
This post explains
the thought process behind our decision –
which is a change
from the current specification.&lt;/p&gt;
&lt;h2 id=&quot;how-the--selector-works-when-nesting&quot;&gt;How the &lt;code&gt;&amp;amp;&lt;/code&gt; selector works, when nesting &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/scope/parent-selector/#how-the--selector-works-when-nesting&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;CSS nesting gave us the &lt;code&gt;&amp;amp;&lt;/code&gt; selector.
When used in a nested context,
it ‘represents’ the parent selector
wrapped with &lt;code&gt;:is()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.parent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp; &gt; .child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be ‘de-sugared’
to conventional un-nested syntax:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:is(.parent)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;:is(.parent) &gt; .child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;amp;&lt;/code&gt; has been swapped out,
and replaced by the parent selector.
It matches the same elements as the parent selector,
with the same specificity.
In the examples above
(where &lt;code&gt;&amp;amp;&lt;/code&gt; is the start of the selector)
we’re allowed to leave it out
and &lt;em&gt;imply&lt;/em&gt; the relationship.
This has exactly the same behavior
and specificity as our examples above:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.parent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&gt; .child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we add the &lt;code&gt;&amp;amp;&lt;/code&gt; to the selector,
the implicit &lt;code&gt;&amp;amp;&lt;/code&gt; is not applied.
These two rules are the same:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.parent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;.context &gt; &amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.context &gt; :is(.parent)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that &lt;code&gt;&amp;amp;&lt;/code&gt;…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Represents the parent selector, matching the same elements&lt;/li&gt;
&lt;li&gt;Is implied at the start unless explicitly placed in a nested selector&lt;/li&gt;
&lt;li&gt;Implicit and explicit starting &lt;code&gt;&amp;amp;&lt;/code&gt; match the same elements&lt;/li&gt;
&lt;li&gt;Implicit and explicit starting &lt;code&gt;&amp;amp;&lt;/code&gt; have the same specificity&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-the-scope-selector-works&quot;&gt;How the &lt;code&gt;:scope&lt;/code&gt; selector works &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/scope/parent-selector/#how-the-scope-selector-works&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Despite &lt;code&gt;@scope&lt;/code&gt; being new in CSS,
‘scoped’ styles have existed for some time,
and the &lt;code&gt;:scope&lt;/code&gt; pseudo-class has
a well-established behavior.
The main examples I’m familiar with
are the JavaScript &lt;code&gt;querySelector()&lt;/code&gt; methods.
Since the query is run on an element,
the &lt;code&gt;:scope&lt;/code&gt; pseudo-class represents
that ‘scope root’ element.
When left out,
it is implied at the start of the selector –
so these two queries select the same elements:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;parentElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;parentElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;:scope a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, if we move &lt;code&gt;:scope&lt;/code&gt; elsewhere in the selector,
it’s no longer implied at the start.
The following will match links in scope
when the scope is also inside an element
with the &lt;code&gt;.context&lt;/code&gt; class:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;parentElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.context :scope a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While it has been less useful,
&lt;code&gt;:scope&lt;/code&gt; is also allowed in plain CSS,
where it behaves the same as &lt;code&gt;:root&lt;/code&gt;.
Since there is no other scope root defined,
the implied scope is the document root.
And since &lt;code&gt;:scope&lt;/code&gt; is a pseudo-class,
it has the specificity of a class selector.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;:scope&lt;/code&gt;…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Represents the single scope-root element&lt;/li&gt;
&lt;li&gt;Is implied at the start unless explicitly placed in a scoped selector&lt;/li&gt;
&lt;li&gt;Implicit and explicit starting &lt;code&gt;:scope&lt;/code&gt; match the same element&lt;/li&gt;
&lt;li&gt;Implicit and explicit starting &lt;code&gt;:scope&lt;/code&gt; have &lt;em&gt;different&lt;/em&gt; specificity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since only the specificity is different,
we can think of the implicit scope as being
something like &lt;code&gt;:where(:scope)&lt;/code&gt; –
with zero specificity.&lt;/p&gt;
&lt;h2 id=&quot;how-the-scope-rule-works&quot;&gt;How the &lt;code&gt;@scope&lt;/code&gt; rule works &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/scope/parent-selector/#how-the-scope-rule-works&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The new &lt;code&gt;@scope&lt;/code&gt; rule
allows authors to define scoped styles in CSS.
This has a lot of &lt;a href=&quot;https://css.oddbird.net/scope/nesting/&quot;&gt;overlap with nesting&lt;/a&gt;,
because (until now)
the default ‘descendant combinator’
has been our best approximation
of the scope use-case.&lt;/p&gt;
&lt;p&gt;These two selectors are similar,
and should match the same elements –
a &lt;code&gt;.child&lt;/code&gt; class
descendant of the &lt;code&gt;#parent&lt;/code&gt; ID.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#parent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;.child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@scope&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;.child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But the &lt;code&gt;@scope&lt;/code&gt; rule
is intended for filtering only,
and does not add any implicit specificity.
We can see how that is the result
of the behavior we described above,
by making the implicit selectors explicit.
The nested selector here
has a specificity
of the parent ID and child class together,
while the scoped selector
only has the child class specificity:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#parent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* specificity: 1,1,0 */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp; .child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@scope&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* specificity: 0,1,0 */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;:where(:scope) .child&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we add bare declarations
inside an &lt;code&gt;@scope&lt;/code&gt; rule,
the behavior is similar.
These two &lt;code&gt;color&lt;/code&gt; declarations
have the same
meaning and specificity:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@scope&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;:where(:scope)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; green&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-does--represent-when-scoping&quot;&gt;What does &lt;code&gt;&amp;amp;&lt;/code&gt; represent, when scoping? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/scope/parent-selector/#what-does--represent-when-scoping&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The question is what it means to use
&lt;code&gt;&amp;amp;&lt;/code&gt; in an &lt;code&gt;@scope&lt;/code&gt; context.&lt;/p&gt;
&lt;h3 id=&quot;the-original-spec&quot;&gt;The original spec &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/scope/parent-selector/#the-original-spec&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A scoped &lt;code&gt;&amp;amp;&lt;/code&gt;
could refer to the &lt;code&gt;&amp;lt;scope-start&amp;gt;&lt;/code&gt; &lt;em&gt;selector&lt;/em&gt;
(&lt;code&gt;#parent&lt;/code&gt; in the previous example).
But then adding the &lt;code&gt;&amp;amp;&lt;/code&gt;
at the start of a selector
changes both the specificity
and also what it can match:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@scope&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;.parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* - only selects the :scope itself */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* - specificity of 0,0,0 */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin dotted&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* - selects any .parent that is in-scope */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* - specificity of 0,1,0 */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin dotted&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was the initial shape of the specification,
but was raised as
an &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9740&quot;&gt;issue by Roman Komarov&lt;/a&gt;.
While &lt;code&gt;&amp;amp;&lt;/code&gt; here can be seen as
‘referencing the parent selector’,
the resulting behavior is actually quite different
from the way &lt;code&gt;&amp;amp;&lt;/code&gt; works in a nested context.
The decision to add it or leave it off
has a big impact on the meaning and specificity of a style.&lt;/p&gt;
&lt;p&gt;An author is given multiple options,
all with subtly different behavior
that might be hard to learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bare declarations match only the scope-root at zero specificity&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:where(:scope)&lt;/code&gt; is the same as the implicit behavior&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:scope&lt;/code&gt; matches only the scope root, with 1-class specificity&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; matches based on a selector, with that selector’s specificity&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-proposed-change&quot;&gt;The proposed change &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/scope/parent-selector/#the-proposed-change&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;But if we think of &lt;code&gt;&amp;amp;&lt;/code&gt; instead as
‘referencing the implicit context’ of a selector,
we can fix that.
From that perspective,
the ‘parent selector’ of an &lt;code&gt;@scope&lt;/code&gt; rule
is actually &lt;code&gt;:where(:scope)&lt;/code&gt; –
since that’s the selector added implicitly
at the start of scoped selectors.
Now three of these selectors behave the same:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@scope&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;.parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* - only selects the :scope itself */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* - specificity of 0,0,0 */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin dotted&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;:where(:scope)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin dotted&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin dotted&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* same behavior, different specificity */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;:scope&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin dotted&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;amp;&lt;/code&gt; &lt;em&gt;behaves&lt;/em&gt; the same way as it does
when nesting,
representing our implicit parent context directly.
Adding or removing the implicit &lt;code&gt;&amp;amp;&lt;/code&gt;
gives us the same results.
That allows authors
to use &lt;code&gt;&amp;amp;&lt;/code&gt; consistently in both
nested and scoped contexts,
as a reference to the implicit selector
which will otherwise be prepended.&lt;/p&gt;
&lt;p&gt;This is
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9740#issuecomment-3028423633&quot;&gt;the solution we resolved on&lt;/a&gt;
during the scope breakout session –
but we plan to re-visit
with the full group next week.&lt;/p&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/"/>
    <updated>2025-06-16T17:30:54Z</updated>
    <id>https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/</id><title>
        Changes to: Physical/logical properties, keywords, and functions
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Clarify &lt;span class=&quot;caps&quot;&gt;SVG&lt;/span&gt; properties, and change&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;title&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Clarify &lt;span class=&quot;caps&quot;&gt;SVG&lt;/span&gt; properties, and change&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;title&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This list is based on the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference&quot;&gt;MDN properties reference&lt;/a&gt;,
and the
&lt;a href=&quot;https://www.w3.org/Style/CSS/all-properties.en.html&quot;&gt;index of CSS properties&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have attempted to capture
all the places where axis or side
is implied by the order of values –
which includes
(but is not limited to)
shorthand properties.
For example,
&lt;code&gt;background-position&lt;/code&gt; is a shorthand
for &lt;code&gt;background-position-x&lt;/code&gt; and &lt;code&gt;background-position-y&lt;/code&gt; –
but &lt;code&gt;object-position&lt;/code&gt; uses the same syntax
without having individual longhand sub-properties.&lt;/p&gt;
&lt;p&gt;This is not meant to be a prescriptive list
of which properties &lt;em&gt;should&lt;/em&gt; provide logical alternatives,
but a descriptive list
of what properties &lt;em&gt;could&lt;/em&gt; be toggled
from one syntax to another.&lt;/p&gt;
&lt;p&gt;Apart from properties,
all &lt;code&gt;&amp;lt;basic-shape&amp;gt;&lt;/code&gt; functions,
transform functions,
and gradient functions currently use physical syntax –
and there have been various requests for logical alternatives.
It’s not clear to me on first-glance
if a logical/physical toggle could (or should)
change how those functions are parsed.&lt;/p&gt;
&lt;p&gt;As a side-note,
I also captured where we have
physical keywords without logical alternatives,
although that’s clearly tangential to the syntax-toggle issue,
since they are explicit to an axis or side.
Still, they seem relevant to a larger question
of providing logical alternatives wherever it is useful.&lt;/p&gt;
&lt;p&gt;I think the next step is to sort these
into groups by shared syntax,
and describe how a toggle
(either local or global)
would apply to each.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://opencollective.com/oddbird-open-source/contribute/css-logical-shorthands-86141&quot;&gt;You can support this effort&lt;/a&gt;
or &lt;a href=&quot;https://css.oddbird.net/logical/&quot;&gt;read more about it&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;multi-value-properties&quot;&gt;Multi-value properties &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/#multi-value-properties&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These accept multiple dimensions in a single syntax,
but don’t have associated sub-properties
for the dimensions involved.
Ideally, a global toggle would apply here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aspect-ratio&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;box-shadow&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text-shadow&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;… (&lt;code&gt;*-position&lt;/code&gt; is listed with shorthands)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background-size&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-repeat&lt;/code&gt; physical (x/y) &lt;em&gt;and keywords&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-image&lt;/code&gt;…
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;border-image-outset&lt;/code&gt; physical (trbl)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-image-repeat&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-image-slice&lt;/code&gt; physical (trbl)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-image-width&lt;/code&gt; physical (trbl)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask&lt;/code&gt;…
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mask-position&lt;/code&gt; physical (x/y) &lt;em&gt;with offset keywords&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-repeat&lt;/code&gt; physical (x/y) &lt;em&gt;and keywords&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-position&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-border&lt;/code&gt;…
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mask-border-outset&lt;/code&gt; physical (trbl)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-border-repeat&lt;/code&gt; physical (x/y)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-border-slice&lt;/code&gt; physical (trbl)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-border-width&lt;/code&gt; physical (trbl)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;object-position&lt;/code&gt; physical (x/y) &lt;em&gt;with offset keywords&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offset-position&lt;/code&gt; physical (x/y) &lt;em&gt;with offset keywords&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;perspective-origin&lt;/code&gt; physical (x/y) &lt;em&gt;with offset keywords&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transform&lt;/code&gt;… (see related functions as well)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;transform-origin&lt;/code&gt; physical (x/y) &lt;em&gt;with offset keywords&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rotate&lt;/code&gt; physical (x/y/z)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scale&lt;/code&gt; physical (x/y/z)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;translate&lt;/code&gt; physical (x/y/z)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No change needed…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;border-spacing&lt;/code&gt; logical (columns &amp;amp; rows)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;column-width&lt;/code&gt; &amp;amp; proposed &lt;code&gt;column-height&lt;/code&gt; are flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;view-timeline-inset&lt;/code&gt; is controlled by &lt;code&gt;view-timeline-axis&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;shorthand-properties&quot;&gt;Shorthand properties &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/#shorthand-properties&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These shorthands accept dimensions,
which can be set individually using sub-properties.
Some of them have logical as well as physical
long-hand properties available,
while some are missing either the physical or logical alternative.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background-position&lt;/code&gt; (&lt;code&gt;*-x&lt;/code&gt; &amp;amp; &lt;code&gt;*-y&lt;/code&gt;) &lt;em&gt;with offset keywords&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;missing&lt;/strong&gt;: &lt;code&gt;*-inline&lt;/code&gt; &amp;amp; &lt;code&gt;*-block&lt;/code&gt;
(&lt;a href=&quot;https://drafts.csswg.org/css-backgrounds-4/&quot;&gt;ED level 4&lt;/a&gt;, unpublished)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;size&lt;/code&gt; (&lt;code&gt;width&lt;/code&gt; &amp;amp; &lt;code&gt;height&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;inline-size&lt;/code&gt; &amp;amp; &lt;code&gt;block-size&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border&lt;/code&gt;…
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;border-width&lt;/code&gt; (&lt;code&gt;border-&amp;lt;trbl&amp;gt;-width&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;border-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;-width&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-style&lt;/code&gt; (&lt;code&gt;border-&amp;lt;trbl&amp;gt;-style&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;border-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;-style&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-color&lt;/code&gt; (&lt;code&gt;border-&amp;lt;trbl&amp;gt;-color&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;border-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;-color&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-radius&lt;/code&gt; (&lt;code&gt;border-&amp;lt;trbl&amp;gt;-radius&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;border-&amp;lt;block&amp;gt;-&amp;lt;inline&amp;gt;-color&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border-image&lt;/code&gt; (see sub-properties above)
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;missing&lt;/strong&gt;: logical &lt;code&gt;-outset&lt;/code&gt;, &lt;code&gt;-repeat&lt;/code&gt;, &lt;code&gt;-slice&lt;/code&gt;, &amp;amp; &lt;code&gt;-width&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inset&lt;/code&gt; (&lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt;, &amp;amp; &lt;code&gt;left&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;inset-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;contain-intrinsic-size&lt;/code&gt; (&lt;code&gt;contain-intrinsic-width&lt;/code&gt; &amp;amp; &lt;code&gt;*-height&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;contain-intrinsic-&amp;lt;axis&amp;gt;-size&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;margin&lt;/code&gt; (&lt;code&gt;margin-&amp;lt;trbl&amp;gt;&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;margin-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-margin&lt;/code&gt; (&lt;code&gt;scroll-margin-&amp;lt;trbl&amp;gt;&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;scroll-margin-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;padding&lt;/code&gt; (&lt;code&gt;padding-&amp;lt;trbl&amp;gt;&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;padding-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-padding&lt;/code&gt; (&lt;code&gt;scroll-padding-&amp;lt;trbl&amp;gt;&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;scroll-padding-&amp;lt;axis&amp;gt;-&amp;lt;side&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-border&lt;/code&gt; (see sub-properties above)
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;missing&lt;/strong&gt;: logical &lt;code&gt;-outset&lt;/code&gt;, &lt;code&gt;-repeat&lt;/code&gt;, &lt;code&gt;-slice&lt;/code&gt;, &amp;amp; &lt;code&gt;-width&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;overflow&lt;/code&gt; (&lt;code&gt;overflow-x&lt;/code&gt; &amp;amp; &lt;code&gt;overflow-y&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;overflow-&amp;lt;axis&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;overflow-behavior&lt;/code&gt; (&lt;code&gt;*-x&lt;/code&gt; &amp;amp; &lt;code&gt;*-y&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;available: &lt;code&gt;overflow-behavior-&amp;lt;axis&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No change needed…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;border&lt;/code&gt; defines all sides equally&lt;/li&gt;
&lt;li&gt;&lt;code&gt;outline&lt;/code&gt;/&lt;code&gt;outline-width&lt;/code&gt; defines all sides equally&lt;/li&gt;
&lt;li&gt;&lt;code&gt;overflow-clip-margin&lt;/code&gt; defines all sides equally&lt;/li&gt;
&lt;li&gt;&lt;code&gt;columns&lt;/code&gt; already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gap&lt;/code&gt; already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;animation-range&lt;/code&gt; controlled by &lt;code&gt;*-timeline-axis&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;keywords&quot;&gt;Keywords &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/#keywords&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since keywords clearly establish physical/logical directions,
they would not be impacted by a global ‘switch’ –
but it’s still useful to know
where logical functionality might be missing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background-repeat&lt;/code&gt; has &lt;code&gt;repeat-x&lt;/code&gt; &amp;amp; &lt;code&gt;repeat-y&lt;/code&gt; keywords
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;missing&lt;/strong&gt; &lt;code&gt;repeat-inline&lt;/code&gt; &amp;amp; &lt;code&gt;repeat-block&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask-repeat&lt;/code&gt; has &lt;code&gt;repeat-x&lt;/code&gt; &amp;amp; &lt;code&gt;repeat-y&lt;/code&gt; keywords
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;missing&lt;/strong&gt; &lt;code&gt;repeat-inline&lt;/code&gt; &amp;amp; &lt;code&gt;repeat-block&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Properties including
&lt;code&gt;background-position&lt;/code&gt;, &lt;code&gt;mask-position&lt;/code&gt;, &lt;code&gt;object-position&lt;/code&gt;,
&lt;code&gt;offset-position&lt;/code&gt;, &lt;code&gt;fill-position&lt;/code&gt;, and &lt;code&gt;stroke-position&lt;/code&gt;
all use the
&lt;a href=&quot;https://drafts.csswg.org/css-values-5/#typedef-position&quot;&gt;&lt;code&gt;&amp;lt;position&amp;gt;&lt;/code&gt; syntax&lt;/a&gt;
with optional offset keywords.
That allows for positioning relative to
either a physical or logical edge
without any toggle on the property parsing itself.&lt;/p&gt;
&lt;p&gt;No change needed…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;caption-side&lt;/code&gt; (&lt;code&gt;top&lt;/code&gt; &amp;amp; &lt;code&gt;bottom&lt;/code&gt;) are flow-relative,
along with &lt;code&gt;inline-start&lt;/code&gt; and &lt;code&gt;inline-end&lt;/code&gt; alternatives
to &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clear&lt;/code&gt; has both logical &amp;amp; physical keywords&lt;/li&gt;
&lt;li&gt;&lt;code&gt;float&lt;/code&gt; has both logical &amp;amp; physical keywords
(including page-floats)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flex-*&lt;/code&gt; &amp;amp; &lt;code&gt;grid-*&lt;/code&gt; already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;margin-trim&lt;/code&gt; already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-snap-align&lt;/code&gt; already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-snap-type&lt;/code&gt; has both logical &amp;amp; physical keywords&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-timeline-axis&lt;/code&gt; has both logical &amp;amp; physical keywords&lt;/li&gt;
&lt;li&gt;&lt;code&gt;place-*&lt;/code&gt; and sub-properties, already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;position-area&lt;/code&gt; already flow-relative&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resize&lt;/code&gt; has both logical &amp;amp; physical keywords&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text-align&lt;/code&gt; has both logical &amp;amp; physical keywords&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text-align-last&lt;/code&gt; has both logical &amp;amp; physical keywords&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azimuth&lt;/code&gt; logical dimensions have no meaning here&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;functions&quot;&gt;Functions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/#functions&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;All &lt;code&gt;&amp;lt;basic-shape&amp;gt;&lt;/code&gt; functions use &lt;strong&gt;physical&lt;/strong&gt; dimensions
&lt;ul&gt;
&lt;li&gt;Impacts &lt;code&gt;clip-path&lt;/code&gt;, &lt;code&gt;shape-outside&lt;/code&gt;, &lt;code&gt;offset-path&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Deprecated &lt;code&gt;clip&lt;/code&gt; (for &lt;code&gt;rect()&lt;/code&gt; only)&lt;/li&gt;
&lt;li&gt;Never implemented &lt;code&gt;shape-inside&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rotate()&lt;/code&gt;, &lt;code&gt;translate()&lt;/code&gt;, and &lt;code&gt;scale()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Impacts &lt;code&gt;transform&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;various &lt;code&gt;gradient()&lt;/code&gt; functions
&lt;ul&gt;
&lt;li&gt;Impacts all image properties&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;svg&quot;&gt;SVG &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-16t173054000z/#svg&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most SVG-related properties
such as &lt;code&gt;cx&lt;/code&gt; and &lt;code&gt;cy&lt;/code&gt; only provide physical syntax.
However, the &lt;code&gt;text-anchor&lt;/code&gt; property
only has &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; values,
with no physical variant.
We could consider adding physical keywords
for &lt;code&gt;text-anchor&lt;/code&gt;,
but I don’t see any need for a syntax toggle.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;fill&lt;/code&gt; &amp;amp; &lt;code&gt;stroke&lt;/code&gt; properties
have &lt;code&gt;*-image&lt;/code&gt;, &lt;code&gt;*-position&lt;/code&gt;, &lt;code&gt;*-size&lt;/code&gt;, and &lt;code&gt;*-repeat&lt;/code&gt;
sub-properties specified –
but not currently implemented.
Any changes to similar background/border productions,
should apply here.
I think this is the only place a syntax toggle
would impact SVGs.&lt;/p&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/logical/properties/2025-06-12t210337000z/"/>
    <updated>2025-06-12T21:03:37Z</updated>
    <id>https://css.oddbird.net/changelog/logical/properties/2025-06-12t210337000z/</id><title>
        Changes to: Physical/logical properties, keywords, and functions
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;The position type does support logical offset&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;keywords&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;The position type does support logical offset&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;keywords&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-12t210337000z/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-12t210337000z/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/logical/properties/2025-06-12t202531000z/"/>
    <updated>2025-06-12T20:25:31Z</updated>
    <id>https://css.oddbird.net/changelog/logical/properties/2025-06-12t202531000z/</id><title>
        Changes to: Physical/logical properties, keywords, and functions
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Provide more context in a&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;summary&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Provide more context in a&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;summary&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-12t202531000z/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/logical/properties/2025-06-12t202531000z/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry><entry>
    <link href="https://css.oddbird.net/logical/properties/"/>
    <updated>2025-06-12T18:54:44Z</updated>
    <id>https://css.oddbird.net/logical/properties/</id><title>
        New page: Physical/logical properties, keywords, and functions
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/properties/&quot;&gt;
          Physical/logical properties, keywords, and functions »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/logical/properties/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/logical/properties/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry><entry>
    <link href="https://css.oddbird.net/logical/research/"/>
    <updated>2025-03-26T00:00:00Z</updated>
    <id>https://css.oddbird.net/logical/research/</id><title>
        New page: Logical shorthand notes &amp; side quests
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/research/&quot;&gt;
          Logical shorthand notes &amp;amp; side quests »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/research/&quot;&gt;
          Logical shorthand notes &amp;amp; side quests »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;h2 id=&quot;why-inline-size-but-padding-inline&quot;&gt;Why &lt;code&gt;inline-size&lt;/code&gt; but &lt;code&gt;padding-inline&lt;/code&gt;? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/logical/research/#why-inline-size-but-padding-inline&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a question from
&lt;a href=&quot;https://mastodon.social/@johanwestling/114220721222033597&quot;&gt;@johanwestling on Mastodon&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But why the opposite property naming order?
I mean &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;padding-block&lt;/code&gt;, &lt;code&gt;padding-inline&lt;/code&gt; for example.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wasn’t in the CSS Working Group
when this decision was made,
but here’s what I’ve found so far.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;December 2010
Writing Modes spec defines terms
&lt;code&gt;length&lt;/code&gt; (logical &lt;code&gt;height&lt;/code&gt;)
and &lt;code&gt;measure&lt;/code&gt; (logical &lt;code&gt;width&lt;/code&gt;)
&lt;a href=&quot;https://www.w3.org/TR/2010/WD-css3-writing-modes-20101202/#dimensions&quot;&gt;https://www.w3.org/TR/2010/WD-css3-writing-modes-20101202/#dimensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;March 2014
Writing-Modes spec uses
&lt;code&gt;extent&lt;/code&gt; (block) &amp;amp; &lt;code&gt;measure&lt;/code&gt; (inline):
&lt;a href=&quot;https://www.w3.org/TR/2014/CR-css-writing-modes-3-20140320/#abstract-dimensions&quot;&gt;https://www.w3.org/TR/2014/CR-css-writing-modes-3-20140320/#abstract-dimensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;March 2014
CSSWG resolves to use
&lt;code&gt;inline-(something)&lt;/code&gt; and &lt;code&gt;block-(something)&lt;/code&gt; instead:
&lt;a href=&quot;https://lists.w3.org/Archives/Public/www-style/2014Mar/0255.html&quot;&gt;https://lists.w3.org/Archives/Public/www-style/2014Mar/0255.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;March 2014 The discussion is mostly about
what &lt;code&gt;(something)&lt;/code&gt; should be,
and agreeing that a hyphen makes
&lt;code&gt;block-size&lt;/code&gt; more clear than &lt;code&gt;block size&lt;/code&gt;
(the 2D size of a block?):
&lt;a href=&quot;https://lists.w3.org/Archives/Public/www-style/2014Mar/0479.html&quot;&gt;https://lists.w3.org/Archives/Public/www-style/2014Mar/0479.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;July 2014 first commit to Logical Properties spec
includes &lt;code&gt;length&lt;/code&gt; and &lt;code&gt;measure&lt;/code&gt; as the property names:
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/blob/156b081188738ea7ecd1aa6a168e4347d339b19f/css-logical-props/Overview.bs&quot;&gt;https://github.com/w3c/csswg-drafts/blob/156b081188738ea7ecd1aa6a168e4347d339b19f/css-logical-props/Overview.bs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;October 2014 the properties are updated to
&lt;code&gt;inline-size&lt;/code&gt; and &lt;code&gt;block-size&lt;/code&gt;:
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/commit/0a24110043cb3f3033fb22661297046a54465eda&quot;&gt;https://github.com/w3c/csswg-drafts/commit/0a24110043cb3f3033fb22661297046a54465eda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;December 2015
Writing Modes spec uses &lt;code&gt;inline-size&lt;/code&gt; and &lt;code&gt;block-size&lt;/code&gt;: &lt;a href=&quot;https://www.w3.org/TR/2015/CR-css-writing-modes-3-20151215/#abstract-axes&quot;&gt;https://www.w3.org/TR/2015/CR-css-writing-modes-3-20151215/#abstract-axes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;May 2017
First Public Working Draft of Logical Properties:
&lt;a href=&quot;https://www.w3.org/TR/2017/WD-css-logical-1-20170518/&quot;&gt;https://www.w3.org/TR/2017/WD-css-logical-1-20170518/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues?q=is%3Aissue%20&amp;amp;page=377&quot;&gt;Github issues only go back to late 2015&lt;/a&gt;,
after the names seem to be settled,
so I can’t find any discussion there.&lt;/p&gt;
&lt;p&gt;Many of the people participating in those conversations
are still involved with the CSSWG today,
so I can ask around for more information –
but it seems to me that the likely answer is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The logical &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;, and &lt;code&gt;border&lt;/code&gt; properties
were added as longhand versions of existing properties,
with the well established &lt;code&gt;&amp;lt;base-property&amp;gt;-&amp;lt;sub-property&amp;gt;&lt;/code&gt; syntax.&lt;/li&gt;
&lt;li&gt;At the time, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; were not longhand properties
with a shared shorthand base-property,
and so the logical alternatives were not designed
as longhand sub-properties.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inline-size&lt;/code&gt; and &lt;code&gt;block-size&lt;/code&gt; already existed as conceptual terms,
and they read better than the flipped &lt;code&gt;size-inline&lt;/code&gt; and &lt;code&gt;size-block&lt;/code&gt;.
Without a shorthand property to base the names off,
there’s little reason to change them.&lt;/li&gt;
&lt;li&gt;Now that we are adding a &lt;code&gt;size&lt;/code&gt; shorthand,
the pattern seems inconsistent –
but it wasn’t even a consideration previously.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/scope/2025-03-25t185952000z/"/>
    <updated>2025-03-25T18:59:52Z</updated>
    <id>https://css.oddbird.net/changelog/scope/2025-03-25t185952000z/</id><title>
        Changes to: CSS Scope &amp; Encapsulation
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Scope is part of Interop&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;2025&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/scope/&quot;&gt;
          CSS Scope &amp;amp; Encapsulation »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Scope is part of Interop&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;2025&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/scope/&quot;&gt;
          CSS Scope &amp;amp; Encapsulation »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;progress:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;Scope is shipping
as part of &lt;a href=&quot;https://wpt.fyi/interop-2025&quot;&gt;Interop&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;2025&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;Authors often complain that CSS is “globally scoped” –
so that every selector is compared against every DOM element.&lt;/p&gt;
&lt;p&gt;There are several overlapping concerns here,
based on a wide range of use-cases –
and they can quickly become confused.
That has lead to a wide array of proposals
that are sometimes working towards different goals.&lt;/p&gt;
&lt;p&gt;Both shadow-DOM
and the abandoned “scope” specification
were focused around strong isolation.
Shadow-DOM in particular creates persistent DOM-defined boundaries,
that impact all style rules.&lt;/p&gt;
&lt;p&gt;Meanwhile,
most of the user-land “scope” tools for CSS
have a much lighter touch.
I’ve been mainly interested in those low-isolation,
namespacing problems.&lt;/p&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/logical/"/>
    <updated>2025-03-25T00:00:00Z</updated>
    <id>https://css.oddbird.net/logical/</id><title>
        New page: CSS Logical Shorthands
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/&quot;&gt;
          CSS Logical Shorthands »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/logical/&quot;&gt;
          CSS Logical Shorthands »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;The CSS Working Group recently resolved
to add a &lt;code&gt;size&lt;/code&gt; shorthand
for setting both the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; of an element.
Many people asked about using it to set the ‘logical’
&lt;code&gt;inline-size&lt;/code&gt; and &lt;code&gt;block-size&lt;/code&gt; properties instead.
But ‘logical shorthands’ have been
stalled in the working group for years.
&lt;em&gt;Can we get them unstuck?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://opencollective.com/oddbird-open-source/contribute/css-logical-shorthands-86141&quot;&gt;You can support our efforts&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/logical/#next-steps&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Research what properties would be impacted&lt;/li&gt;
&lt;li&gt;Choose syntax for individual properties&lt;/li&gt;
&lt;li&gt;Develop lexical toggle to allow default-logical styles&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;css-working-group-discussion&quot;&gt;CSS Working Group discussion &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/logical/#css-working-group-discussion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Specification: &lt;a href=&quot;https://www.w3.org/TR/css-logical/&quot;&gt;CSS Logical Properties&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fantasai opened the original issue in 2017,
when publishing the &lt;a href=&quot;https://www.w3.org/TR/2017/WD-css-logical-1-20170518/&quot;&gt;First Public Working Draft&lt;/a&gt;
of CSS Logical Properties:
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1282#issue-223656679&quot;&gt;[css-logical] Flow-relative syntax for margin-like shorthands&lt;/a&gt;.
Here are some key comments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-952428897&quot;&gt;2021 proposed solution&lt;/a&gt;
by &lt;a href=&quot;https://css.oddbird.net/elsewhere/21-brooklyn/&quot;&gt;Fantasai &amp;amp; Miriam &amp;amp; Jen Simmons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-1249685175&quot;&gt;2022 TPAC discussion&lt;/a&gt;
with &lt;a href=&quot;https://www.w3.org/groups/wg/i18n-core/&quot;&gt;Internationalization Working Group&lt;/a&gt; (I18n) –
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-1249822796&quot;&gt;Tab summarizes the decision to be made&lt;/a&gt;,
but the next step is
&lt;em&gt;making a list of impacted properties&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-1719113776&quot;&gt;2023 update for I18n WG&lt;/a&gt; –
&lt;em&gt;still waiting on the research&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-2372647118&quot;&gt;2024 update for I18n WG&lt;/a&gt; –
&lt;em&gt;still waiting on research&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;other-resources&quot;&gt;Other resources &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/logical/#other-resources&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Jeremy Keith, 2022: &lt;a href=&quot;https://adactio.com/journal/19457&quot;&gt;Let’s get logical&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Miriam, 2022: &lt;a href=&quot;https://www.miriamsuzanne.com/2022/09/16/tpac-logical/&quot;&gt;A long-term plan for logical shorthands?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OddBird, 2025: &lt;a href=&quot;https://www.oddbird.net/2025/03/20/logical-shorthand/&quot;&gt;Support logical shorthands in CSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/layers/link-layer/"/>
    <updated>2024-06-18T00:00:00Z</updated>
    <id>https://css.oddbird.net/layers/link-layer/</id><title>
        New page: Cascade Layering of HTML Linked Style Sheets
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/layers/link-layer/&quot;&gt;
          Cascade Layering of HTML Linked Style Sheets »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/layers/link-layer/&quot;&gt;
          Cascade Layering of HTML Linked Style Sheets »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;h2 id=&quot;authors&quot;&gt;Authors &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#authors&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Miriam Suzanne&lt;/p&gt;
&lt;h2 id=&quot;participate&quot;&gt;Participate &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#participate&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are discussion threads
on both the WHATWG and CSSWG
github repos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(WHATWG #7540)
&lt;a href=&quot;https://github.com/whatwg/html/issues/7540&quot;&gt;Allow authors to apply new css features (like cascade layers) while linking stylesheets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(CSSWG #5853)
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/5853&quot;&gt;Provide an attribute for assigning a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; to a cascade layer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#introduction&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cascade layers
allow CSS authors to
create explicit cascade priority tiers,
and place style sheets into those tiers
using either a block at-rule (&lt;code&gt;@layer&lt;/code&gt;)
or a condition on the &lt;code&gt;@import&lt;/code&gt; rule
(&lt;code&gt;layer&lt;/code&gt; or &lt;code&gt;layer(layer-name)&lt;/code&gt;).
The details are defined in
&lt;a href=&quot;https://www.w3.org/TR/css-cascade-5/&quot;&gt;CSS Cascading and Inheritance Level 5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the primary use-cases
for cascade layering
is to manage the priority
of third-party CSS
(libraries and design systems)
in relation to site-specific styles.
However,
there are many situations
where authors do not want to use &lt;code&gt;@import&lt;/code&gt;
for performance reasons,
or cannot use &lt;code&gt;@import&lt;/code&gt;
because of build tooling.
Providing this functionality on the HTML &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag
would bring it in better alignment with
the CSS import functionality.&lt;/p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#goals&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The motivating use-case
is quite specific:
a syntax for assigning linked style sheets
to a cascade layer.&lt;/p&gt;
&lt;p&gt;This should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allow assigning styles to either named or anonymous layers&lt;/li&gt;
&lt;li&gt;Invalidate links if a layer name is invalid,
or cascade layers are unsupported&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;non-goals&quot;&gt;Non-goals &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#non-goals&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This raises issues of compatibility.
For some period of time,
there will be browsers that do not support
the new layering syntax.
If those browsers apply the linked styles
without applying the appropriate layer rules,
the results will be unexpected and unreliable.&lt;/p&gt;
&lt;p&gt;Ideally,
browsers without support for a layering syntax
should not load layered style sheets.
With the appropriate tools
for support-conditioned links,
authors could then choose to load
alternative style sheets.&lt;/p&gt;
&lt;p&gt;However,
that would currently require
changes to the &lt;code&gt;media&lt;/code&gt; or &lt;code&gt;type&lt;/code&gt; attributes.
Looking farther out,
the WHATWG discussion seems to prefer
a separate/new attribute for support conditions,
since they are not technically treated
as media queries in CSS.
The details of that proposal
seem to be blocking progress
on the less controversial &lt;code&gt;layer&lt;/code&gt; attribute
proposed below.
For that reason,
I’ve set aside support conditions
as a non-goal for this document.&lt;/p&gt;
&lt;p&gt;Authors can polyfill conditional loading as desired,
with a small amount of javascript
to detect feature support,
and alter the existing &lt;code&gt;media&lt;/code&gt; attribute as needed.&lt;/p&gt;
&lt;h2 id=&quot;proposed-solution-the-layer-attribute&quot;&gt;Proposed solution: the &lt;code&gt;layer&lt;/code&gt; attribute &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#proposed-solution-the-layer-attribute&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;layer&lt;/code&gt; attribute
applies to both &lt;code&gt;link&lt;/code&gt; and &lt;code&gt;style&lt;/code&gt; elements,
with the following behaviors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;missing&lt;/em&gt;: The style sheet is not assigned to any cascade layer&lt;/li&gt;
&lt;li&gt;&lt;em&gt;empty string&lt;/em&gt;: The style sheet is assigned to an anonymous layer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;layer-name&amp;gt;&lt;/code&gt;: The style sheet is assigned to the named cascade layer.
As with &lt;code&gt;@import&lt;/code&gt;,
the layer is added to the layer order
even if the link fails to load the style sheet,
but is subject to any other link conditions (such as &lt;code&gt;media&lt;/code&gt;).
This is just as if the layer was declared by an &lt;code&gt;@layer&lt;/code&gt; rule
wrapped in the appropriate conditional group rules.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;none of the above&lt;/em&gt;: The link is invalidated,
and the style sheet should not load.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is designed to match the behavior
of the &lt;code&gt;layer&lt;/code&gt; keyword and &lt;code&gt;layer()&lt;/code&gt; function
in the &lt;a href=&quot;https://www.w3.org/TR/css-cascade-5/#at-import&quot;&gt;CSS import syntax&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that the
&lt;a href=&quot;https://html.spec.whatwg.org/#attributes-2&quot;&gt;empty attribute syntax&lt;/a&gt;
sets the value implicitly
to the &lt;em&gt;empty string&lt;/em&gt; –
so the &lt;code&gt;layer&lt;/code&gt; attribute can be applied
as though it is a boolean attribute,
resulting in an anonymous layer.&lt;/p&gt;
&lt;h2 id=&quot;key-scenarios&quot;&gt;Key scenarios &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#key-scenarios&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Existing style sheet links
without the &lt;code&gt;layer&lt;/code&gt; attribute
should continue to work
without any changes:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- no layering is applied --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;example.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;screen.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;screen&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When working with resets,
third-party libraries, and design systems,
authors may want to apply layers on-import.
This is especially common since site authors
may not have access to edit the style sheet,
but still want to manage cascade priority
of the resulting styles:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- site.css can define layer order, and internal layering --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;site.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- external styles can be assigned existing layers, or create new ones --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;library/styles.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;framework.library&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;reset.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;reset&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;design/system.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;framework.system&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In some cases,
authors might want to wrap styles
in an anonymous layer
that can’t be accessed later.
This can be used to enforce code order,
or simply move a reset
to the lowest cascade position:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- anonymously push a reset into a lower layer --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;site.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;reset.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- enforce layer rules are grouped in relevant files --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;defaults.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;patterns.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;components.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;layer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When given an invalid layer name
the style sheets will not apply.
That ensures a typo doesn’t apply
un-layered style contents
which would have the highest cascade-priority.&lt;/p&gt;
&lt;h2 id=&quot;detailed-design-discussion&quot;&gt;Detailed design discussion &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#detailed-design-discussion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it would be nice to ship this
along with a broader import-condition syntax,
the details of that syntax
have been contentious.
However, the need for a new &lt;code&gt;layer&lt;/code&gt; attribute,
and the general shape of that attribute
have not been controversial.&lt;/p&gt;
&lt;p&gt;It might be worth noting
that other CSS features are likely to need
similar dedicated attributes.
For example,
the &lt;code&gt;@scope&lt;/code&gt; block rule may warrant
a &lt;code&gt;scope()&lt;/code&gt; import rule
and &lt;code&gt;scope&lt;/code&gt; attribute.
However, this is the exception for CSS –
and only needed for larger architectural features.
It is not likely to become a common request.&lt;/p&gt;
&lt;h2 id=&quot;stakeholder-feedback--opposition&quot;&gt;Stakeholder Feedback / Opposition &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#stakeholder-feedback--opposition&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Authors have been asking when it will happen.
Implementors have been positive in the linked discussions.
Now that there is an explainer to reference directly,
I will ask for more explicit standards positions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blink: TBD&lt;/li&gt;
&lt;li&gt;WebKit: TBD&lt;/li&gt;
&lt;li&gt;Gecko: TBD&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;references--acknowledgements&quot;&gt;References &amp;amp; acknowledgements &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/layers/link-layer/#references--acknowledgements&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Many thanks for valuable feedback and advice from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discussions in the CSSWG &amp;amp; WHATWG&lt;/li&gt;
&lt;li&gt;Simon Pieters&lt;/li&gt;
&lt;li&gt;Florian Rivoal&lt;/li&gt;
&lt;li&gt;Adreu Botella&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/"/>
    <updated>2024-02-11T20:20:37Z</updated>
    <id>https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/</id><title>
        Changes to: CSS Mixins &amp; Functions Explainer
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Changes to variable scope and function result&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;syntax&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Changes to variable scope and function result&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;syntax&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;h2 id=&quot;author&quot;&gt;Author &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#author&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Miriam Suzanne&lt;/p&gt;
&lt;p&gt;(Based heavily on a custom-function proposal by Tab Atkins)&lt;/p&gt;
&lt;h2 id=&quot;intro&quot;&gt;Intro &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#intro&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to reduce code repetition,
ensure consistency across a project,
and encourage best practice,
authors have often turned to third-party
CSS pre-processors
(Sass, Less, PostCSS, Stylus, etc)
to define custom reusable ‘macros’.
These generally fall into two categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Functions&lt;/strong&gt; return CSS &lt;em&gt;values&lt;/em&gt; –
like a string, color, or length.
They can only be used &lt;em&gt;inside&lt;/em&gt;
the value space of a CSS property.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mixins&lt;/strong&gt; return CSS &lt;em&gt;declarations&lt;/em&gt;
or entire &lt;em&gt;rule blocks&lt;/em&gt;.
They can only be used &lt;em&gt;outside&lt;/em&gt;
the value space of a CSS property.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CSS already provides a wide range
of built-in functions,
such as &lt;code&gt;calc()&lt;/code&gt;, &lt;code&gt;minmax()&lt;/code&gt;, and many more.
Ideally, custom functions would work in a similar way,
but prefixed with a dashed-ident
to avoid future compatibility issues.
For a simple example:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; --negative &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-1 * &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--negative&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--gap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CSS does not yet have built-in mixins,
though several have been proposed
in discussions of this feature.
A simple mixin might look something like this:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@mixin&lt;/span&gt; --button &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--face&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; --text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; --radius&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--face&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;in lch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 85%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--background&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--border-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;in lch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 80%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--background&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@result&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--background&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; medium double &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--border-color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--radius&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 3px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.25lh 2ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;button[type=&#39;submit&#39;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rebeccaPurple&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;button.danger&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maroon&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;discussion&quot;&gt;Discussion &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#discussion&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Discussion on CSSWG Drafts
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350&quot;&gt;Proposal: Custom CSS Functions &amp;amp; Mixins (#9350)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Existing proposal for
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7490&quot;&gt;Declarative custom functions (#7490)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Issue tracker
for this explainer:
&lt;a href=&quot;https://github.com/oddbird/css-sandbox/issues&quot;&gt;OddBird CSS Sandbox Issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are several other relevant discussions
in the CSS Working Group,
that predate this proposal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7879&quot;&gt;[css-variables-2] Custom shorthands with @property #7879&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7490&quot;&gt;Declarative custom functions #7490&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/5624&quot;&gt;[css-variables?] Higher level custom properties that control multiple declarations #5624&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(If there are more I haven’t found,
please &lt;a href=&quot;https://github.com/oddbird/css-sandbox/issues&quot;&gt;let me know&lt;/a&gt;.)&lt;/p&gt;
&lt;!--
..######..##.....##.##.....##.##.....##....###....########..##....##
.##....##.##.....##.###...###.###...###...##.##...##.....##..##..##.
.##.......##.....##.####.####.####.####..##...##..##.....##...####..
..######..##.....##.##.###.##.##.###.##.##.....##.########.....##...
.......##.##.....##.##.....##.##.....##.#########.##...##......##...
.##....##.##.....##.##.....##.##.....##.##.....##.##....##.....##...
..######...#######..##.....##.##.....##.##.....##.##.....##....##...
--&gt;
&lt;h2 id=&quot;summary--goals&quot;&gt;Summary &amp;amp; Goals &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#summary--goals&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Features often change
as they move from (generally imperative)
pre-processors into CSS –
taking on different affordances and constraints
appropriate for a declarative,
client-side language:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How would CSS-native mixins and functions
differ from pre-processors?&lt;/li&gt;
&lt;li&gt;What extra functionality or limitations
come from providing these features
in the browser?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From a language/implementation perspective
mixins and functions
are entirely distinct features –
they live at different levels of the syntax,
and come with different complications.
If we pursue both,
we likely want to define them at
different levels of a specification,
or even in different specifications.&lt;/p&gt;
&lt;p&gt;Removing the reliance on pre-processors
would further simplify maintenance for CSS authors,
while providing new client-side functionality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passing cascaded custom-properties as arguments.&lt;/li&gt;
&lt;li&gt;Adding media/support and other client-side conditions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My goal here is to explore
what would be possible with each feature,
where we could re-use syntax between them,
and how we might move forward
with implementing them.&lt;/p&gt;
&lt;p&gt;I am not expecting this to be the final shape
for either feature,
but I want to capture the state of the conversation,
and help move it forward.
If these features are officially
adopted by the working group,
further development can be broken
into individual specs and issues.&lt;/p&gt;
&lt;!--
.####.##....##.########.########.########..########..######..########
..##..###...##....##....##.......##.....##.##.......##....##....##...
..##..####..##....##....##.......##.....##.##.......##..........##...
..##..##.##.##....##....######...########..######....######.....##...
..##..##..####....##....##.......##...##...##.............##....##...
..##..##...###....##....##.......##....##..##.......##....##....##...
.####.##....##....##....########.##.....##.########..######.....##...
--&gt;
&lt;h2 id=&quot;author-interest&quot;&gt;Author Interest &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#author-interest&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There is some (incomplete) data
from the HTTP Archive project
that can help us understand
how authors are using Sass currently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/5798&quot;&gt;Stats on Scss usage of control flow, conditional logic, nesting, custom functions #5798&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also ran a small &lt;a href=&quot;https://front-end.social/@mia/110833306689188274&quot;&gt;survey on Mastodon&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“What are the most common custom functions or mixins
that you define/use in a css pre-processor?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The answers included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(Functions) Conversion from pixel to &lt;code&gt;rem&lt;/code&gt; units&lt;/li&gt;
&lt;li&gt;(Functions) random number generators&lt;/li&gt;
&lt;li&gt;(Functions) Color contrast&lt;/li&gt;
&lt;li&gt;(Mixins) Named shorthands for common media queries&lt;/li&gt;
&lt;li&gt;(Mixins) Generating output from object for-each loops (like Sass Maps)&lt;/li&gt;
&lt;li&gt;(Mixins) Reusable component styles&lt;/li&gt;
&lt;li&gt;(Mixins) Complex solutions, like scroll-shadows or gradient text&lt;/li&gt;
&lt;li&gt;(Both) Fluid typography settings&lt;/li&gt;
&lt;li&gt;(Both) Complex &lt;code&gt;calc()&lt;/code&gt; shorthands for various situations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of these would be possible to achieve
in CSS with a declarative syntax,
without additional new functionality.
Others (like loops) would require imperative control structures.&lt;/p&gt;
&lt;p&gt;While some of these (like &lt;code&gt;random()&lt;/code&gt;)
are already being discussed for built-in functions,
others (like &lt;code&gt;color-contrast()&lt;/code&gt;)
may be simpler to solve in user-space.
It has been very difficult for the CSSWG
to settle on a long-term solution
for the entire platform,
while an individual team would be
more able to change their approach gradually over time.
By capturing that logic in a single place
(like a custom function),
many changes could be made without
any invasive re-write of the code base.&lt;/p&gt;
&lt;p&gt;The ability to declare this logic in CSS
rather than a pre-processor
would provide several benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Reduce the external dependencies&lt;/em&gt; and build steps
required in order to generate the code&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Reduce the file size delivered&lt;/em&gt; from the server
(though this may be negligible after compression &amp;amp;
increased client-side processing)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;use custom properties as arguments&lt;/em&gt;
so that the mixins or functions
could respond to changes in the cascade&lt;/li&gt;
&lt;li&gt;&lt;em&gt;use media/container/support conditions&lt;/em&gt;
as part of the internal logic&lt;/li&gt;
&lt;/ul&gt;
&lt;!--
.########.....###....########.....###....##.....##..######.
.##.....##...##.##...##.....##...##.##...###...###.##....##
.##.....##..##...##..##.....##..##...##..####.####.##......
.########..##.....##.########..##.....##.##.###.##..######.
.##........#########.##...##...#########.##.....##.......##
.##........##.....##.##....##..##.....##.##.....##.##....##
.##........##.....##.##.....##.##.....##.##.....##..######.
--&gt;
&lt;h2 id=&quot;defining-parameters&quot;&gt;Defining parameters &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#defining-parameters&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Both functions and mixins
rely on a &lt;code&gt;&amp;lt;parameter-list&amp;gt;&lt;/code&gt; syntax.
Each &lt;code&gt;&amp;lt;parameter&amp;gt;&lt;/code&gt;
in the &lt;code&gt;&amp;lt;parameter-list&amp;gt;&lt;/code&gt;
consists of three parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;name&amp;gt;&lt;/code&gt; (required)
which is a &lt;code&gt;dashed-ident&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;syntax&amp;gt;&lt;/code&gt; (default: &lt;code&gt;*&lt;/code&gt;)
similar to the &lt;code&gt;syntax&lt;/code&gt; descriptor in &lt;code&gt;@property&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;default-value&amp;gt;&lt;/code&gt; (default: &lt;code&gt;guaranteed invalid&lt;/code&gt;)
which is any value that matches the syntax&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Defining all three aspects in the function prelude
(name, type, and default)
can make the syntax over-complicated.
My initial proposal
included special &lt;code&gt;@property&lt;/code&gt;-like
descriptor blocks to make that possible.&lt;/p&gt;
&lt;p&gt;Since then,
the discussion has moved towards
a more concise approach
using a comma-separated list.&lt;/p&gt;
&lt;p&gt;Authors can provide names only:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--my-function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--param-a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; --another-param&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Optionally,
they can also provide a default value:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--my-function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--param-a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1em&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--another-param&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;this is a string&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Note:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;Since the list is comma-separated,
this would require
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9539&quot;&gt;better handling of arguments with commas&lt;/a&gt;
in&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;Finally,
authors could define
a syntax for any parameter,
using the &lt;code&gt;type()&lt;/code&gt; function
along side the name.
This would work with or without default values:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--my-function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  --param-a &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --another-param &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1em&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!--
.########.##.....##.##....##..######..########.####..#######..##....##..######.
.##.......##.....##.###...##.##....##....##.....##..##.....##.###...##.##....##
.##.......##.....##.####..##.##..........##.....##..##.....##.####..##.##......
.######...##.....##.##.##.##.##..........##.....##..##.....##.##.##.##..######.
.##.......##.....##.##..####.##..........##.....##..##.....##.##..####.......##
.##.......##.....##.##...###.##....##....##.....##..##.....##.##...###.##....##
.##........#######..##....##..######.....##....####..#######..##....##..######.
--&gt;
&lt;h2 id=&quot;defining-a-function-the-function-rule&quot;&gt;Defining a function: the &lt;code&gt;@function&lt;/code&gt; rule &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#defining-a-function-the-function-rule&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to define a custom function,
we need several bits of information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;function-name&lt;/code&gt; (required)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parameter-list&lt;/code&gt; (optional - see above)&lt;/li&gt;
&lt;li&gt;Some amount of internal logic using &lt;code&gt;function-rules&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A returned &lt;code&gt;result&lt;/code&gt; value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The proposed syntax
(with a few adjustments)
could look something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@function &amp;lt;function-name&amp;gt; [( &amp;lt;parameter-list&amp;gt; )]? {
  &amp;lt;function-rules&amp;gt;

  result: &amp;lt;result&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;function-name&lt;/code&gt; is a dashed-ident.
If multiple functions have the same name,
then functions in a higher cascade layer take priority,
and functions defined later have priority
within a given cascade layer.
This matches the behavior of other name-defining at-rules.&lt;/p&gt;
&lt;p&gt;It may also be useful to define an intended ‘return type’
(e.g. &lt;code&gt;color&lt;/code&gt; or &lt;code&gt;length&lt;/code&gt;) for the function,
so that it can be validated at parse time.
Like custom properties,
there is still a chance that a function’s output
will be &lt;em&gt;invalid at computed value time&lt;/em&gt;,
but we can at least ensure that
the function is intended to return an appropriate syntax
for the context where it is being called.&lt;/p&gt;
&lt;p&gt;Extending the above syntax,
I would imagine re-using the &lt;code&gt;type()&lt;/code&gt; function
in the prelude:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@function &amp;lt;function-name&amp;gt; [( &amp;lt;parameter-list&amp;gt; )]? [returns type(&amp;lt;syntax&amp;gt;)]? {
  &amp;lt;function-rules&amp;gt;

  result: &amp;lt;result&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I would expect &lt;code&gt;&amp;lt;syntax&amp;gt;&lt;/code&gt; to allows the same
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@property/syntax#values&quot;&gt;subset of CSS Types&lt;/a&gt;
provided by the &lt;code&gt;syntax&lt;/code&gt; descriptor of the &lt;code&gt;@property&lt;/code&gt; rule.
Maybe it would be possible to remove
the requirement for quotes around a syntax in this context?&lt;/p&gt;
&lt;h3 id=&quot;returning-values&quot;&gt;Returning values &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#returning-values&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There have been several syntax options discusses
for returning a &lt;code&gt;&amp;lt;result&amp;gt;&lt;/code&gt; value,
but it seems to me like the simplest
and most familiar would be a descriptor
called something like &lt;code&gt;result&lt;/code&gt; or &lt;code&gt;output&lt;/code&gt;.
This would help re-enforce
the declarative nature of functions,
since it can be treated similar to other declarations:
the last &lt;code&gt;result&lt;/code&gt; is used if multiple are present.&lt;/p&gt;
&lt;p&gt;Like custom properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;result&amp;gt;&lt;/code&gt; can contain any valid CSS value-space syntax&lt;/li&gt;
&lt;li&gt;This value has &lt;code&gt;invalid at computed value time&lt;/code&gt; behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since functions exist in the value space,
&lt;code&gt;&amp;lt;function-rules&amp;gt;&lt;/code&gt; will not contain any other
(non-custom) CSS properties,
so the single &lt;code&gt;result&lt;/code&gt; descriptor should stand out.
If multiple results are encountered,
the last result takes precedence
(consistent with other descriptors and properties).
This is discussed in more detail below.&lt;/p&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Note:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;Tab covers
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1930463996&quot;&gt;declarative execution in the &lt;span class=&quot;caps&quot;&gt;CSSWG&lt;/span&gt; issue&lt;/a&gt;
with a bit more&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;detail.&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;h3 id=&quot;function-rules&quot;&gt;Function rules &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#function-rules&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;function-rules&amp;gt;&lt;/code&gt; can include custom property declarations
(which are scoped to the function),
as well as conditional at-rules
(which may contain further nested
custom properties and &lt;code&gt;result&lt;/code&gt;s).
Element-specific conditions (such as container queries)
would be resolved for each element that calls the function.&lt;/p&gt;
&lt;p&gt;My assumption
would be that custom properties
defined inside the function
are not available
on elements where the function is called.
However, it’s clear that authors will expect
to reference external custom properties
from inside functions –
using some variation of dynamic scope,
and ‘shadowing’ behavior.&lt;/p&gt;
&lt;p&gt;As far as I can tell,
only custom properties, args/variables,
and conditional rules
are useful inside a function definition.
Functions have no output
besides their returned value,
so nested selectors, built-in properties,
and name-defining rules
are not necessary or meaningful.
I don’t think there’s any need for these things
to invalidate the entire function,
but they should be ignored and discarded.&lt;/p&gt;
&lt;p&gt;An example function
using conditional rules
to return one of multiple values:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--sizes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  --s &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --m &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --l &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; returns &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 16px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inline-size &amp;lt; 20em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--s&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;20em &amp;lt; inline-size &amp;lt; 50em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1em + 0.5vw&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;50em &amp;lt; inline-size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--l&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1.2em + 1vw&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some functions will also want access to
contextual variables
on the calling elements.
To avoid fully dynamic scoping
of custom properties,
Tab has proposed a second list
of properties that should be available
in the function:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; --my-function &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--arg1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; --arg2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; using &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--var1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; --var2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* --arg1 and --arg2 can be provided as arguments */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* --var1 and --var2 will shadow identically-named variables&lt;br /&gt;     in the calling context */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Note:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;Tab covers
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1930463996&quot;&gt;variable scoping in the &lt;span class=&quot;caps&quot;&gt;CSSWG&lt;/span&gt; issue&lt;/a&gt;
with a bit more&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;detail.&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;h3 id=&quot;calling-functions&quot;&gt;Calling functions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#calling-functions&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Custom functions can be called
from the value space of any property,
with the name of the functions,
followed by parenthesis and
a comma-separated list of arguments:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pink&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0.7&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we do (eventually) want to support named arguments,
it would ideally use a familiar
declaration syntax:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.7&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If positional and named arguments
are allowed in the same function call,
the common convention is to require
all positional values come before any named values
to avoid confusion:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.7&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to allow a broad
syntax for argument values –
including values that contain commas.
There’s an active discussion
about the best way to handle this
more generally in
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9539&quot;&gt;issue #9539&lt;/a&gt;.
Custom functions should use whatever solution
is agreed on there.&lt;/p&gt;
&lt;h3 id=&quot;putting-it-all-together&quot;&gt;Putting it all together &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#putting-it-all-together&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Adapting the fluid ratio function above
to the proposed syntax:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--fluid-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  --min-width &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --max-width &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; returns &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;percentage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min-width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 300px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--max-width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 2000px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;l&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--scale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--max&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100vw - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--fraction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--position&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--scale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clamp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    0%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    100% * &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--fraction&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    100%&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;--fluid-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;375px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 1920px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1.25rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;--fluid-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;375px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 700px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 2rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could also consider moving the &lt;code&gt;mix()&lt;/code&gt; logic
into the function:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--fluid-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  --min-value &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --max-value &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --from-width &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --to-width &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; returns &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from-width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--fluid-min&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 375px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--to-width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--fluid-max&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1920px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--scale&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--to&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100vw - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--fraction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--position&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--scale&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--progress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clamp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 100% * &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--fraction&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--progress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min-value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--max-value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--fluid-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1.25rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--fluid-mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 2rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 375px&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 700px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!--
.##.....##.####.##.....##.####.##....##..######.
.###...###..##...##...##...##..###...##.##....##
.####.####..##....##.##....##..####..##.##......
.##.###.##..##.....###.....##..##.##.##..######.
.##.....##..##....##.##....##..##..####.......##
.##.....##..##...##...##...##..##...###.##....##
.##.....##.####.##.....##.####.##....##..######.
--&gt;
&lt;h2 id=&quot;defining-a-mixin-the-mixin-rule&quot;&gt;Defining a mixin: the &lt;code&gt;@mixin&lt;/code&gt; rule &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#defining-a-mixin-the-mixin-rule&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Rather than returning a single value,
mixins return entire declarations
and potentially entire nested rule blocks.
While much of the function syntax
could be re-purposed,
we would need an additional way
to manage property scoping –
clearly marking what rule blocks are internal,
and which should be part of the output.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@mixin &amp;lt;mixin-name&amp;gt; [( &amp;lt;parameter-list&amp;gt; )]? {
  &amp;lt;mixin-rules&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, when there are multiple mixins
that use the same name,
the last mixin with that name
takes precedence.&lt;/p&gt;
&lt;h3 id=&quot;mixin-rules-and-output&quot;&gt;Mixin rules and output &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#mixin-rules-and-output&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The simplest approach
to nested rules and output
would be to treat the inside of a mixin definition
the same as any rule-block nested context.
Anything we can put inside a rule block
can be put inside a mixin,
and will be output where the mixin is called
(with any parameters being replaced first).
This will work for many simpler cases:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@mixin&lt;/span&gt; --center-content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;place-content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.page&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; --center-content&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/*&lt;br /&gt;    display: grid;&lt;br /&gt;    place-content: center;&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;--clearfix &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token parent important&quot;&gt;&amp;amp;&lt;/span&gt;::after &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; both&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flow-root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flow-root&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token parent important&quot;&gt;&amp;amp;&lt;/span&gt;::after &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.float-container &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  @apply --clearfix&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/*&lt;br /&gt;    &amp;amp;::after {&lt;br /&gt;      display: block;&lt;br /&gt;      content: &quot;&quot;;&lt;br /&gt;      clear: both;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @supports (display: flow-root) {&lt;br /&gt;      display: flow-root;&lt;br /&gt;&lt;br /&gt;      &amp;amp;::after { display: none; }&lt;br /&gt;    }&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach doesn’t allow
the mixin to contain any internal logic
scoped to the mixin itself.
Mixins should be able to
use internally scoped custom-properties,
and also optionally &lt;em&gt;output&lt;/em&gt; custom properties
as part of the returned rule block.
As things stand,
this doesn’t seem relevant
to anything other than custom properties.
Built-in properties, selectors, and at-rules
are only useful for their output.&lt;/p&gt;
&lt;p&gt;Given that this issue is specific to custom properties,
we could consider a flag such as &lt;code&gt;!private&lt;/code&gt;.
That flag could be interesting
for custom properties in other contexts,
but I won’t follow that path unless there’s interest.
Alternatively,
we could explicitly mark
blocks of content
with either &lt;code&gt;@output&lt;/code&gt; or &lt;code&gt;@private&lt;/code&gt; at-rules.&lt;/p&gt;
&lt;h3 id=&quot;applying-mixins-the-new-apply-rule&quot;&gt;Applying mixins: the (new) &lt;code&gt;@apply&lt;/code&gt; rule &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#applying-mixins-the-new-apply-rule&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order to apply a mixin,
we use an &lt;code&gt;@apply&lt;/code&gt; rule:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;@apply &amp;lt;mixin-name&gt; [&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&amp;lt;argument-list&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;]?&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;argument-list&amp;gt;&lt;/code&gt; syntax
should ideally match the function argument notation.&lt;/p&gt;
&lt;p&gt;When the mixin is resolved,
the output of the mixin
is inserted where the apply rule was called:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* declaration */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.float-container&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; --clearfix&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/* result */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.float-container&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp;::after&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; both&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flow-root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flow-root&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;&amp;amp;::after&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is an additional question
about how to handle mixin output
at the top level of the document
(not nested inside a selector):&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; --center-content&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As long as there is a selector wrapping the output,
this should not be an issue.
Even if that selector is simply
the parent reference &lt;code&gt;&amp;amp;&lt;/code&gt;,
that has a well-defined behavior
at the top level of documents –
referring to the current &lt;code&gt;:scope&lt;/code&gt;.
However, if the result is bare declarations
without any selector,
they should be discarded and ignored.&lt;/p&gt;
&lt;p&gt;Another example,
from a Sass mixin I’ve used on occasion:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--gradient-text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  --from-color &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --to-color &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --at-angle &lt;span class=&quot;token function&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;angle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--to-color&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from-color&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mediumvioletred&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--angle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--at-angle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; to bottom right&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--to&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--angle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--to&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--gradient&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--from&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--gradient-text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pink&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; powderblue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!--
.##..........###....##....##.########.########...######.
.##.........##.##....##..##..##.......##.....##.##....##
.##........##...##....####...##.......##.....##.##......
.##.......##.....##....##....######...########...######.
.##.......#########....##....##.......##...##.........##
.##.......##.....##....##....##.......##....##..##....##
.########.##.....##....##....########.##.....##..######.
--&gt;
&lt;h2 id=&quot;layers-of-complexity&quot;&gt;Layers of complexity &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#layers-of-complexity&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The popular Sass functions and mixins
demonstrate a range of different input needs,
from relatively static shorthands,
to fully imperative control structures.&lt;/p&gt;
&lt;h3 id=&quot;simple-shorthands&quot;&gt;Simple shorthands &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#simple-shorthands&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;clearfix&lt;/code&gt; mixin
often has no exposed ‘parameters’,
and no internal logic.
When the mixin is invoked,
it will output
the same code every time.
This is useful for maintaining
DRY code (Don’t Repeat Yourself),&lt;/p&gt;
&lt;p&gt;Static mixins like this
end up very similar to
‘utility classes’ such as &lt;code&gt;.clearfix&lt;/code&gt;.
However, mixins still have the advantage
that they can be applied in CSS,
rather than HTML.
The need for CSS control
comes into focus when combined
with &lt;code&gt;@media&lt;/code&gt;/&lt;code&gt;@container&lt;/code&gt; and other conditional logic.
There is currently no way in CSS
to write this code without
defining all the custom properties twice:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.dark-mode&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* more custom props as needed… */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;html:not(.light-mode)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* more custom props as needed… */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most of the existing proposals around this use-case
would combine conditional logic
with selector logic,
so that both can be defined at once.
In Sass, we might fix this instead
by providing a &lt;code&gt;dark-mode&lt;/code&gt; mixin
that can be used multiple times
to output the same declarations
with only minimal repetition:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;dark-mode &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* more custom props as needed… */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.dark-mode &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; dark-mode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;.light-mode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; dark-mode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using Container Style Queries
might also be an option here.
They can be somewhat &lt;em&gt;mixin-like&lt;/em&gt;,
but come with all the limitations
of container queries.
If we set a custom property &lt;code&gt;--mode&lt;/code&gt;
on the root &lt;code&gt;html&lt;/code&gt; element,
we have to assign properties on a different element
than we query:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.dark-mode&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;html:not(.light-mode)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@container&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;--mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* The html element cannot query itself */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* more custom props as needed… */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That can cause several problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are optimizations and features specific to the root,
that can’t be replicated on other elements.&lt;/li&gt;
&lt;li&gt;In other component contexts,
it’s likely to require extra markup.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While no-parameter mixins like these
are somewhat common,
it’s much less common to have a
function without parameters,
since a simple value
can be captured in a variable
or custom property instead.&lt;/p&gt;
&lt;h3 id=&quot;built-in-conditions&quot;&gt;Built-in conditions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#built-in-conditions&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It can also be useful to provide mixins
that have no author-facing parameters,
but still contain internal logic and conditional statements –
using &lt;code&gt;@supports&lt;/code&gt;, &lt;code&gt;@media&lt;/code&gt;, or &lt;code&gt;@container&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;gradient-text &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;to bottom right&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mediumvioletred&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;-webkit-text-fill-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A mixin like this might even
reference external values
by relying on custom properties
without accepting explicit override parameters:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;gradient-text &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--gradient-text-start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--color-primary&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--gradient-text-end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--color-complement&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mediumvioletred&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--gradient-text-start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;      to bottom right&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--gradient-text-start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--gradient-text-end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;-webkit-text-fill-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;accepting-parameters&quot;&gt;Accepting parameters &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#accepting-parameters&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most common reason
to use a function or mixin
is the ability to define parameters
that alter the output
based on different input.
For example, a
&lt;code&gt;darken()&lt;/code&gt; function
would accept two parameters:
a color,
and an amount to darken that color.&lt;/p&gt;
&lt;p&gt;In many cases (like &lt;code&gt;darken()&lt;/code&gt;)
the internal function logic
can be represented by an inline calculation
using existing CSS features.
In those situations,
a custom function could still provide
more concise and easy-to-use shorthand
around a more complex &lt;code&gt;calc()&lt;/code&gt;
or relative color adjustment.&lt;/p&gt;
&lt;h3 id=&quot;parameter-conditions&quot;&gt;Parameter conditions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#parameter-conditions&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once we allow both parameters
and conditional logic,
the next step would be to allow
parameters to be used in the conditions themselves.
For example:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;--style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; outline&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;--shape&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pill&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@when&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;--style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; outline&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; medium solid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@else&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; teal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@when&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;--shape&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pill&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;imperative-control-flow&quot;&gt;Imperative control flow &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#imperative-control-flow&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some use-cases require
more complex ‘flow control’
such as loops.
For example,
a combination of mixins might generate
a full color-palette
based on a single origin color.
In Sass,
it might looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@use&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;sass:color&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;@use&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;sass:math&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tint-shade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--&lt;span class=&quot;token variable&quot;&gt;#{$name}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;#{$color}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$step&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; math.&lt;span class=&quot;token function&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;@for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; 1 &lt;span class=&quot;token keyword&quot;&gt;through&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$step&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--&lt;span class=&quot;token variable&quot;&gt;#{$name}&lt;/span&gt;-t&lt;span class=&quot;token variable&quot;&gt;#{$i}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;color.&lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;white&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;--&lt;span class=&quot;token variable&quot;&gt;#{$name}&lt;/span&gt;-s&lt;span class=&quot;token variable&quot;&gt;#{$i}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;color.&lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;black&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;complement&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* generate tints and shades for the main color */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tint-shade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;primary&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; == &#39;complement&#39; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$complement&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; color.&lt;span class=&quot;token function&quot;&gt;adjust&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$hue&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 180deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tint-shade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$complement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;complement&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;@else if&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; == &#39;triad&#39; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;/* logic for triad themes… */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* etc… */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;html &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting output CSS would be:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* generate tints and shades for the main color */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--primary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; blue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--primary-t1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #5555ff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--primary-s1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #0000aa&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--primary-t2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #aaaaff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--primary-s2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #000055&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--complement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yellow&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--complement-t1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #ffff55&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--complement-s1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #aaaa00&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--complement-t2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #ffffaa&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--complement-s2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #555500&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* etc… */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think it would be reasonable
to draw a boundary here,
since CSS is a declarative language.
Adding imperative flows
would likely cause confusion around the execution model.&lt;/p&gt;
&lt;!--
.########..########.########....###....####.##........######.
.##.....##.##..........##......##.##....##..##.......##....##
.##.....##.##..........##.....##...##...##..##.......##......
.##.....##.######......##....##.....##..##..##........######.
.##.....##.##..........##....#########..##..##.............##
.##.....##.##..........##....##.....##..##..##.......##....##
.########..########....##....##.....##.####.########..######.
--&gt;
&lt;h2 id=&quot;detailed-discussion-and-open-questions&quot;&gt;Detailed discussion and open questions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#detailed-discussion-and-open-questions&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;other-result-syntaxes-for-functions&quot;&gt;Other result syntaxes for functions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#other-result-syntaxes-for-functions&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both Lea and I have noted that
it would be useful
if authors could rely on cascade
‘order of appearance’
to provide ‘fallback’ return values.
Sadly, however,
that sort of parse-time fallback
is not possible with dynamic
computed-value-time features
like custom properties or functions.&lt;/p&gt;
&lt;p&gt;I initially proposed an at-rule syntax (&lt;code&gt;@return&lt;/code&gt;),
arguing that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It helps distinguish
the final returned value from any internal logic
like custom properties and nested rules&lt;/li&gt;
&lt;li&gt;Result is not a property,
but looks a lot like one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, &lt;code&gt;result&lt;/code&gt;
does act like a property in many ways,
and would help to re-enforce
our familiarity with declarative execution.
While many imperative languages
allow an ‘eager’ &lt;em&gt;first-takes-precedence&lt;/em&gt; function return,
CSS and other declarative languages
generally uses a &lt;em&gt;last-takes-precedence&lt;/em&gt; approach.
For the same reason,
we should avoid active words like &lt;code&gt;return&lt;/code&gt;
that suggest the evaluation is linear
and can be cut short.&lt;/p&gt;
&lt;p&gt;François Remy
has proposed setting a custom property
with the same name as the function,
and that property is treated as the resulting value.
Lea Verou suggested making the property name
customizable in the prelude.&lt;/p&gt;
&lt;p&gt;I prefer a syntax that is more consistent and reliable.
I don’t see any utility that comes from
allowing this functionality to be renamed in each function,
or requiring that name to be determined by authors,
or putting it in the author’s custom-ident name space.
Those all seem to me like ways of inviting typos and confusion,
without any clear gain.&lt;/p&gt;
&lt;p&gt;Matching the function name
seems to me extra fragile –
as you could never rename one
without also updating the other.
Still,
either approach could work,
and provide the same basic behavior.
We can continue to bike-shed the details.&lt;/p&gt;
&lt;h3 id=&quot;passing-nested-content-to-mixins&quot;&gt;Passing nested content to mixins &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#passing-nested-content-to-mixins&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another common feature of Sass mixins
is the ability to pass nested content blocks
into a mixin,
and have the mixin place that content
in a specific context.
This seems like a feature
that could be supported in CSS as well,
but would require another mixin-specific at-rule
(or similar placeholder).
I’ll call it &lt;code&gt;@nested&lt;/code&gt; for now:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@mixin&lt;/span&gt; --media-medium&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; screen &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--small&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &amp;lt; inline-size &amp;lt; &lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--large&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@nested&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.grid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; --media-medium&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--padding-medium&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The expected behavior would be
the same as writing:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.grid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; screen &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--small&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &amp;lt; inline-size &amp;lt; &lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--large&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--padding-medium&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This seems like something that could be added later,
if necessary.&lt;/p&gt;
&lt;h3 id=&quot;invalid-function-fallbacks&quot;&gt;Invalid function fallbacks &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#invalid-function-fallbacks&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sadly,
last-takes-precedence &lt;code&gt;@return&lt;/code&gt; behavior
doesn’t provide the same benefit here
that it has in the cascade –
where invalid declarations
can be discarded at parse time,
falling back on previously declared values.
In order to achieve that,
we would need to limit functions
so that they are the only value in a property.
I don’t think that tradeoff makes sense
for the use-cases I’ve seen.&lt;/p&gt;
&lt;p&gt;I’m also not sure it makes sense
to provide function-defined fallback values
to return when arguments provided have invalid syntax.
Ideally, function fallbacks
would be modeled after variable fallbacks –
established where the function is called,
rather than where it is defined.
It’s hard to see where this would fit
in the proposed syntax.&lt;/p&gt;
&lt;p&gt;One option would be a &lt;code&gt;var()&lt;/code&gt;-like
wrapper function:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;--contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 0.7&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could even use the existing &lt;code&gt;var()&lt;/code&gt;,
but that would result in functions and custom properties
sharing a single namespace,
which might not be ideal.
Maybe the proposed function for
&lt;code&gt;first-supported()&lt;/code&gt; would also be an option
that has broader use?
This likely needs more bike-shedding.&lt;/p&gt;
&lt;h3 id=&quot;using-parameters-in-conditional-rules&quot;&gt;Using parameters in conditional rules &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#using-parameters-in-conditional-rules&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Above,
I used an example with conditional output
using media queries inside the function.
Authors may reasonably wish to take this farther
and use parameters to define the media queries themselves:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--media&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--breakpoint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--below&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--above&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; length&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; screen &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width &amp;lt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--breakpoint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--below&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; screen &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width &gt;= &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--breakpoint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--above&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a very common use of pre-processor mixins,
and a common use-case for the proposed inline &lt;code&gt;if()&lt;/code&gt;
and &lt;code&gt;media()&lt;/code&gt; functions as well.&lt;/p&gt;
&lt;p&gt;As I understand it,
that will not be possible as written above,
for the same reasons &lt;code&gt;var()&lt;/code&gt; is not currently allowed
in media-query conditions.
However,
the issues are specific to cascaded values
that need to be resolved at computed value time.
Passing static arguments from a parameter
should not pose the same problem.&lt;/p&gt;
&lt;p&gt;If we had a new way of accessing
values passed in –
I’ll use &lt;code&gt;arg()&lt;/code&gt; for the sake of argument –
simple value substitution should be possible:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--media&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--breakpoint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--below&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--above&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; length&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; screen &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width &amp;lt; &lt;span class=&quot;token function&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--breakpoint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--below&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; screen &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width &gt;= &lt;span class=&quot;token function&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--breakpoint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--above&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* this works fine, since the argument is accessed with `var()` */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--media&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;40em&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--padding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* this errors, since the argument is accessed with `arg()` */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--media&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--break&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 40em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above example,
the &lt;code&gt;padding&lt;/code&gt; declaration
would be valid
since a static value
can be passed along to the media query &lt;code&gt;arg()&lt;/code&gt; –
but the &lt;code&gt;margin&lt;/code&gt; declaration would fail
since it supplies a custom property
to a media query condition.&lt;/p&gt;
&lt;p&gt;It’s not clear to me
if parameters used this way
would need to be explicitly marked in advance
for any reason?
As proposed here,
it would be up to function authors
to document and communicate
which parameters can accept cascading variables,
and which can not.&lt;/p&gt;
&lt;h3 id=&quot;argument-conditions-and-loops&quot;&gt;Argument conditions and loops &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#argument-conditions-and-loops&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With both mixins and functions
it can be useful to have conditions
based on the arguments passed in.
For example, we might want to pass in
one of several established keywords,
and return a different value
depending which keyword is used:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--theme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; *&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@when&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--theme&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; light&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--link-light&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@else&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--link-dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s not clear to me
if the proposed &lt;code&gt;@when&lt;/code&gt;/&lt;code&gt;@else&lt;/code&gt; features
can be adapted to this use-case,
or if it would need to be
a distinct set of similar flow controls.&lt;/p&gt;
&lt;p&gt;Similarly,
as we saw in the tint-shade example earlier,
it can be useful to loop over
a set number of repetitions (for loop)
or a set list of items (each loop).&lt;/p&gt;
&lt;p&gt;While these would be helpful features for authors,
they are not required for
(or dependent on)
an initial implementation of mixins or functions.
They feel like distinct features
that would go well together.&lt;/p&gt;
&lt;h3 id=&quot;can-we-allow-the-calc-sum-syntax&quot;&gt;Can we allow the &lt;code&gt;&amp;lt;calc-sum&amp;gt;&lt;/code&gt; syntax? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#can-we-allow-the-calc-sum-syntax&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This question was raised
by &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7490#issuecomment-1256880496&quot;&gt;Brandon McConnell&lt;/a&gt;
in the ‘Declarative Custom Functions’ issue
(see point 5, even though it’s not specific to recursion).
The goal is to provide custom functions
that take raw calc expressions,
without being explicitly wrapped in a nested
&lt;code&gt;calc()&lt;/code&gt; function,
similar to the way other math functions work:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.item&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100% - 1em&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 30em&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the one hand,
custom property substitution
makes it trivial to capture expressions,
and later call them inside a &lt;code&gt;calc()&lt;/code&gt; function.
This already works:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100% - 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hsl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0deg 100% &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To take it farther,
we would need to expose the &lt;code&gt;&amp;lt;calc-sum&amp;gt;&lt;/code&gt;
grammar as a valid syntax
for authors to use.&lt;/p&gt;
&lt;p&gt;It might also be worth considering
what other syntax/types would be useful to expose –
either for parameters specifically,
or for property registration more generally.
It seems ideal to me
if those lists can be kept in alignment.&lt;/p&gt;
&lt;h3 id=&quot;what-about-extend&quot;&gt;What about &lt;code&gt;@extend&lt;/code&gt;? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#what-about-extend&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Sass,
mixins without parameters also
overlap with the &lt;code&gt;@extend&lt;/code&gt; feature,
which is used to combine related classes –
one as an ‘extension’ of the other.
In most cases,
that has the same intended result
as a no-parameter-mixin:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* extends */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin solid maroon&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp;:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fee&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.error--serious&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@extend&lt;/span&gt; .error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thick&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/* mixin */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@mixin&lt;/span&gt; error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thin solid maroon&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;&amp;amp;:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fee&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.error--serious&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@include&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thick&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The difference is that a class definition
can be compiled from multiple rule blocks
in different style sheets,
while a mixin generally has one centralized definition.
This is part of the reason
extensions have become less common in Sass –
it can be difficult to reason about their impact.
For now,
I think mixins would provide the similar functionality
without the same complexity.&lt;/p&gt;
&lt;p&gt;If we are interested in exploring &lt;code&gt;@extend&lt;/code&gt; at some point,
Tab has already written an
&lt;a href=&quot;http://tabatkins.github.io/specs/css-extend-rule/&quot;&gt;unofficial draft specification&lt;/a&gt;
that we can build from.&lt;/p&gt;
&lt;h3 id=&quot;can-functions-be-chained-or-call-themselves&quot;&gt;Can functions be chained, or call themselves? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#can-functions-be-chained-or-call-themselves&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I would expect that it should be possible
to chain function/mixin calls together.
A theme-generating mixin
should be able to reference
a single-color generating mixin or function internally.&lt;/p&gt;
&lt;p&gt;It’s less clear to me if recursive function calls
are possible or necessary.
There are likely use-cases for recursion
as a form of looping,
but I’m not sure how central they are.
This doesn’t seem like a feature requirement in level 1.&lt;/p&gt;
&lt;h3 id=&quot;keyframe-based-mixins-for-interpolated-values&quot;&gt;Keyframe-based mixins for interpolated values? &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#keyframe-based-mixins-for-interpolated-values&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There has been a lot of recent discussion around
&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/6245#issuecomment-1715416464&quot;&gt;interpolating values between breakpoints&lt;/a&gt;
for e.g. responsive typography.
Conceptually, animation keyframes work well
for defining the steps involved –
but in this case the result is not technically animated,
and interpolated values
should ideally not be removed
to the animation origin.&lt;/p&gt;
&lt;p&gt;To get around that,
the most recent proposals
involves a new property
(tentatively &lt;code&gt;interpolate&lt;/code&gt;)
that would accept a keyframes name
and timeline,
then ‘expand in place’
to represent the declarations
in the referenced &lt;code&gt;@keyframes&lt;/code&gt; rule.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@keyframes&lt;/span&gt; typography&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.2em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.4&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* declaration, this is all pseudo-code */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;interpolate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; typography --container-size ease-in&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* result, with interpolated values */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* interpolated… */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* interpolated… */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alan Stearns has pointed out
in conversations
that this is a very mixin-like behavior,
and suggested treating keyframes
as an existing form of mixin,
rather than a new property.
Given the same keyframes above,
we could consider a syntax like:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* mixin, this is all pseudo-code */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;typography&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--container-size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt; ease-in&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* result, with interpolated values */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* interpolated… */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* interpolated… */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If that clutters the mixin namespace,
another approach might be
requiring dashed-ident mixin names,
and providing some built-in mixins such as:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* declaration, this is all pseudo-code */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;keyframes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;typography&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt; --container-size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; ease-in&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;/* result, with interpolated values */&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* interpolated… */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* interpolated… */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!--
.########..########..####..#######..########........###....########..########
.##.....##.##.....##..##..##.....##.##.....##......##.##...##.....##....##...
.##.....##.##.....##..##..##.....##.##.....##.....##...##..##.....##....##...
.########..########...##..##.....##.########.....##.....##.########.....##...
.##........##...##....##..##.....##.##...##......#########.##...##......##...
.##........##....##...##..##.....##.##....##.....##.....##.##....##.....##...
.##........##.....##.####..#######..##.....##....##.....##.##.....##....##...
--&gt;
&lt;h2 id=&quot;prior-art&quot;&gt;Prior art &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#prior-art&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;the-apply-rule-abandoned&quot;&gt;The &lt;code&gt;@apply&lt;/code&gt; Rule (abandoned) &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#the-apply-rule-abandoned&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Links:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;&lt;a href=&quot;https://www.xanthir.com/b4o00&quot;&gt;Why I abandoned &lt;code&gt;@apply&lt;/code&gt;&lt;/a&gt;
by &lt;strong&gt;Tab&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;Atkins-Bittner&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;At one point,
there was a plan
for custom properties to act as a form of mixin,
using the &lt;code&gt;@apply&lt;/code&gt; rule.
That proposal was abandoned
as the wrong approach
for several related reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Custom properties are value-level syntax,
while mixins are declaration-level&lt;/li&gt;
&lt;li&gt;It doesn’t make sense for mixin definitions
to be passed around in the cascade&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are not difficult issues to avoid.
I’m working from the premise that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both function and mixins
should be &lt;em&gt;defined&lt;/em&gt; globally,
and not rely on any element-aware
aspects of the cascade.&lt;/li&gt;
&lt;li&gt;Similar to e.g. &lt;code&gt;@keyframes&lt;/code&gt;,
function and mixin definitions
would still resolve name conflicts
using global cascade features
like &lt;em&gt;layers&lt;/em&gt; and &lt;em&gt;order of appearance&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Functions are applied in the &lt;em&gt;value&lt;/em&gt; space,
while mixins are applied in the &lt;em&gt;declaration&lt;/em&gt; space.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;container-style-queries-partially-implemented&quot;&gt;Container Style Queries (partially implemented) &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#container-style-queries-partially-implemented&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Links:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/css-contain-3/#style-container&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; Containment Module Level&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;3&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;The &lt;code&gt;style()&lt;/code&gt; feature of &lt;code&gt;@container&lt;/code&gt;
can sometimes be used to approximate mixin behavior.
There are several recent
&lt;a href=&quot;https://front-end.social/@chriscoyier/110821892737745155&quot;&gt;posts&lt;/a&gt;
and &lt;a href=&quot;https://chriskirknielsen.com/blog/future-themes-with-container-style-queries/&quot;&gt;articles&lt;/a&gt;
written about that approach.
However, style queries
share the limitation of other container queries:
&lt;em&gt;we can’t style the container being queried&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Container queries are designed
as a &lt;em&gt;conditional selector&lt;/em&gt; mechanism,
for responding to changes in context.
The ancestor/descendant limitation
is required for browsers to separate
selector-matching from value-resolution
on a given element.&lt;/p&gt;
&lt;p&gt;However, &lt;em&gt;mixins do not alter selection&lt;/em&gt;,
they only ‘bundle’ existing CSS rules and declarations for re-use.
Ideally, these two features should work well together,
so that contextual conditions
can change the arguments passed to a given mixin.&lt;/p&gt;
&lt;h3 id=&quot;custom-properties-implemented&quot;&gt;Custom Properties (implemented) &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#custom-properties-implemented&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Links:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2019/07/css-custom-properties-cascade/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; Custom Properties In The Cascade&lt;/a&gt;
by &lt;strong&gt;Miriam&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;Suzanne&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;We can also use custom properties to
approximate some basic mixins and functions.
While these tricks can be useful,
they involve significant complexity,
caveats, and limitations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each ‘function/mixin’ and ‘argument’ is a custom property,
which can only have a single resolved value per element&lt;/li&gt;
&lt;li&gt;Arguments are substituted in the function/mixin
&lt;em&gt;before the computed value inherits&lt;/em&gt;,
so the logic has to be defined
on every element that should re-calculate a result&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;mixins-and-functions-in-pre-processors&quot;&gt;Mixins and functions in pre-processors &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#mixins-and-functions-in-pre-processors&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;details data-alert=&quot;note&quot; open=&quot;&quot;&gt;
            &lt;summary&gt;Links:&lt;/summary&gt;
            &lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://sass-lang.com/documentation/at-rules/function/&quot;&gt;Sass &lt;code&gt;@function&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sass-lang.com/documentation/at-rules/mixin/&quot;&gt;Sass &lt;code&gt;@mixin&lt;/code&gt;/&lt;code&gt;@include&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;In addition to parameters,
Sass mixins can accept &lt;em&gt;content blocks&lt;/em&gt;.
An example &lt;a href=&quot;https://sass-lang.com/documentation/at-rules/mixin/#content-blocks&quot;&gt;from the documentation&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;hover &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &amp;amp;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;[disabled]&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token selector&quot;&gt;:hover &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;@content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.button &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px solid black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;token selector&quot;&gt;hover &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That might be a useful feature
for CSS mixins as well.
It would be required for the use-case
of creating named conditions.
That use-case may also be solved by the proposed
&lt;code&gt;@when&lt;/code&gt; rule and ‘custom media queries’ feature.&lt;/p&gt;
&lt;p&gt;Sass provides some built-in core functions,
but (so far) does not provide core mixins.
Likely for that reason,
the HTTP Archive report lists
several commonly-used built-in functions
(&lt;code&gt;if()&lt;/code&gt;, and &lt;code&gt;darken()&lt;/code&gt;),
but only the most commonly used
custom mixin name (&lt;code&gt;clearfix&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&quot;existing-proposal-for-custom-functions&quot;&gt;Existing Proposal for Custom Functions &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#existing-proposal-for-custom-functions&quot;&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In July of 2022,
Johannes Odland proposed
‘&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7490&quot;&gt;Declarative custom functions&lt;/a&gt;’
in the CSS Working Group issue tracker.
Since then,
the proposal has gone through
several revisions and updates.&lt;/p&gt;
&lt;p&gt;The current (2023-08-08)
proposal in that thread
suggests that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functions would be resolved
at the same time as variable substitution&lt;/li&gt;
&lt;li&gt;Function parameters defined with a CSSOM ‘syntax’
can be validated at parse time
(like &lt;code&gt;@property&lt;/code&gt;-registered variables)&lt;/li&gt;
&lt;li&gt;This would be a declarative version
of the more full-featured Houdini API feature&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are also several example use-cases,
such as this function
for fluid typography:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@custom-function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--fluid-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  --min-width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  --max-width&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clamp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    0%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    100% * &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100vw - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min-width&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--max-width&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--min-width&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    100%&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;--fluid-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;375px&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1920px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1.25rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;--fluid-ratio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;375px&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 700px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 2rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;details data-alert=&quot;warn&quot;&gt;
            &lt;summary&gt;Unit division in math functions:&lt;/summary&gt;
            &lt;div&gt;&lt;p&gt;In addition to the new syntax proposed here,
browsers would also need to implement
&lt;a href=&quot;https://drafts.csswg.org/css-values/#calc-type-checking&quot;&gt;unit-division in math functions&lt;/a&gt;
for this use-case to work as&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;shown.&lt;/p&gt;
&lt;/div&gt;
          &lt;/details&gt;
&lt;p&gt;Or a function for
generating checkerboard background-images:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@custom-function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--checkerboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token property&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;        45deg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        silver 25%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        transparent 25%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        transparent 75%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        silver 75%&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      0px 0px / &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;        45deg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        silver 25%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        transparent 25%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        transparent 75%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        silver 75%&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / 2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / 2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; / &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.used&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;--checkerboard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;32px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For these use-case,
custom functions could be a simple wrapper
for inserting parameters into
existing functions like &lt;code&gt;calc()&lt;/code&gt;.
Tab Atkins has suggested a math-only version of this
would be simplest to implement.
While that might be a useful first-step,
it quickly falls short of the use-cases I’ve seen.
I would prefer to start with a more fully-featured approach,
and work backwards to an attainable level 1 implementation
if needed.&lt;/p&gt;
&lt;p&gt;In addition to some bike-shedding of the syntax,
there are several more open questions in the thread:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can authors provide a fallback output
for invalid arguments?&lt;/li&gt;
&lt;li&gt;Would it be helpful to include default parameter values
in the function definition?&lt;/li&gt;
&lt;li&gt;Can function authors define internally-scoped custom properties?&lt;/li&gt;
&lt;li&gt;Can authors use conditional at-rules
inside the function logic?&lt;/li&gt;
&lt;li&gt;Can functions expose a parameter
that accepts bare calculations (without &lt;code&gt;calc()&lt;/code&gt; syntax)
similar to &lt;code&gt;clamp()&lt;/code&gt; etc?&lt;/li&gt;
&lt;li&gt;Can functions perform recursive function calls?&lt;/li&gt;
&lt;li&gt;Can functions be called with named
(rather than positional) arguments?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope to expand on this proposal,
and explore some of those questions along the way.&lt;/p&gt;
&lt;!--
.##.....##.########.########....###...
.###...###.##..........##......##.##..
.####.####.##..........##.....##...##.
.##.###.##.######......##....##.....##
.##.....##.##..........##....#########
.##.....##.##..........##....##.....##
.##.....##.########....##....##.....##
--&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#acknowledgments&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This proposal is based on
an &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7490&quot;&gt;existing discussion&lt;/a&gt;
with input from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Johannes Odland&lt;/li&gt;
&lt;li&gt;David Baron&lt;/li&gt;
&lt;li&gt;Brian Kardell&lt;/li&gt;
&lt;li&gt;Tab Atkins-Bittner&lt;/li&gt;
&lt;li&gt;@jimmyfrasche&lt;/li&gt;
&lt;li&gt;Brandon McConnell&lt;/li&gt;
&lt;li&gt;Lea Verou&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve also incorporated feedback
along the way from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nicole Sullivan&lt;/li&gt;
&lt;li&gt;Anders Hartvoll Ruud&lt;/li&gt;
&lt;li&gt;Rune Lillesveen&lt;/li&gt;
&lt;li&gt;Alan Stearns&lt;/li&gt;
&lt;li&gt;Yehonatan Daniv&lt;/li&gt;
&lt;li&gt;Emilio Cobos Álvarez&lt;/li&gt;
&lt;li&gt;François Remy&lt;/li&gt;
&lt;li&gt;Steinar H Gunderson&lt;/li&gt;
&lt;li&gt;Matt Giuca&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;todo&quot;&gt;Todo &lt;a class=&quot;header-anchor&quot; href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2024-02-11t202037000z/#todo&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1717661703&quot;&gt;Defer mixin-nested selectors&lt;/a&gt;
as &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1723337386&quot;&gt;potentially expensive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1719603753&quot;&gt;Clarify recursion limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1720836487&quot;&gt;Clarify static vs dynamic args&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry><entry>
    <link href="https://css.oddbird.net/overflow/explainer/"/>
    <updated>2023-12-14T00:00:00Z</updated>
    <id>https://css.oddbird.net/overflow/explainer/</id><title>
        New page: CSS Overflow - Broad Research
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/overflow/explainer/&quot;&gt;
          CSS Overflow - Broad Research »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;New page added&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/overflow/explainer/&quot;&gt;
          CSS Overflow - Broad Research »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/overflow/explainer/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/overflow/explainer/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-12-01t214011000z/"/>
    <updated>2023-12-01T21:40:11Z</updated>
    <id>https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-12-01t214011000z/</id><title>
        Changes to: CSS Mixins &amp; Functions Explainer
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Updates to parameter syntax and variable&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;scope&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Updates to parameter syntax and variable&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;scope&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-12-01t214011000z/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-12-01t214011000z/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-13t080341000z/"/>
    <updated>2023-09-13T08:03:41Z</updated>
    <id>https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-13t080341000z/</id><title>
        Changes to: CSS Mixins &amp; Functions Explainer
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Provide acknowledgments&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Provide acknowledgments&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-13t080341000z/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-13t080341000z/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry><entry>
    <link href="https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-12t174002000z/"/>
    <updated>2023-09-12T17:40:02Z</updated>
    <id>https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-12t174002000z/</id><title>
        Changes to: CSS Mixins &amp; Functions Explainer
      </title><summary type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Document potential built-in keyframes&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;mixin&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;</summary>

    <content type="html">
      &lt;blockquote&gt;
        &lt;p&gt;Document potential built-in keyframes&lt;span class=&quot;widont&quot;&gt;&amp;nbsp;&lt;/span&gt;mixin&lt;/p&gt;

      &lt;/blockquote&gt;

      &lt;p&gt;
        &lt;a href=&quot;https://css.oddbird.net/sasslike/mixins-functions/&quot;&gt;
          CSS Mixins &amp;amp; Functions Explainer »
        &lt;/a&gt;
      &lt;/p&gt;&lt;hr /&gt;&lt;p&gt;This page has more recent changes available. For more details, see:&lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-12t174002000z/#changelog-feed&quot;&gt;current status on css.oddbird.net&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://css.oddbird.net/changelog/sasslike/mixins-functions/2023-09-12t174002000z/#changelog-feed&quot;&gt;log of major changes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;The &lt;a href=&quot;https://github.com/oddbird/css-sandbox/commits/main/src/feed.njk&quot;&gt;github commit history&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;</content>
  </entry>
</feed>


