Last active
February 14, 2024 21:31
-
-
Save joelstransky/935a4447a547d7f95ad399dc073a9c18 to your computer and use it in GitHub Desktop.
SASS mixin for nested children in contained elements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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