Skip to content

Instantly share code, notes, and snippets.

@joelstransky
Last active February 14, 2024 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelstransky/935a4447a547d7f95ad399dc073a9c18 to your computer and use it in GitHub Desktop.
Save joelstransky/935a4447a547d7f95ad399dc073a9c18 to your computer and use it in GitHub Desktop.
SASS mixin for nested children in contained elements
@use "sass:string";
@use "sass:list";
/**
* Use @container just like media-query
* A mixin to ensure contained grand-children are properly selected within their container
* without having to select all the way down from the contained element.
* $child:string - The valid selector you want inserted
* $index:number - The number of shifts to make in the parent selector
* $asSibling:bool - Use sibling combinator after the shift?
**/
@mixin unshift-parent($child, $index: 1, $asSibling: false) {
$spacer: " ";
$stringified: #{&}; // the current selector as a string
$asSplit: string.split($stringified, " ");
$targetNth: list.nth($asSplit, list.length($asSplit) - ($index - 1));
$targetIndex: string.index($stringified, $targetNth);
@if($asSibling) {
$spacer: null;
}
@at-root #{string.insert( #{&}, #{$child$spacer}, $targetIndex)}{@content}
}
/**
* usage
* The following would output
* .parent-element .child {}
* and
* .parent-element .grand-child {}
* but containers need select from the container down and we don't want to lose scope
**/
.parent-element {
background: lightblue;
.child {
padding: 1em;
}
.grand-child {
/**
* this will produce
* @container (min-width: 720px) { .parent-element .grand-child {} }
**/
@container (min-width: 720px) {
.border: 1px solid red;
}
/**
* this will produce
* @container (min-width: 720px) { .parent-element .child .grand-child {} }
**/
@container (min-width: 720px) {
@include unshift-parent(".child", 1) {
.border: 1px solid red;
}
}
/**
* You can even make it a sibling.
* this will produce
* @container (min-width: 720px) { .parent-element .child.grand-child {} }
**/
@container (min-width: 720px) {
@include unshift-parent(".child", 1, true) {
.border: 1px solid red;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment