// -------------------------------------------------- // Mixins used throughout the theme // -------------------------------------------------- // Media queries // -------------------------------------------------- @use "sass:math"; $breakpoints: ( mobile-small: 320px, mobile-medium: 350px, mobile-large: 450px, mobile-extra-large: 550px, tablet: 768px, medium: 850px, large: 1000px, extra-large: 1140px, ); @mixin breakpoint($bp, $rule: max-width, $type: screen, $sidebar: false) { @media #{$type} and (#{$rule}: map-get($breakpoints, $bp)) { @content; } // if you want to consider the sidebar in your breakpoint // you can pass in $sidebar: true // note that your breakpoint will need to be at the root level @if $sidebar { // when the sidebar is shown, we want to increase the breakpoints by the width of the sidebar @media #{$type} and (#{$rule}: calc(#{map-get($breakpoints, $bp)} + #{$d-sidebar-width})) { .has-sidebar-page { @content; } } } } // CSS3 properties // -------------------------------------------------- // Clearfix @mixin clearfix() { &:before, &:after { content: ""; display: table; } &:after { clear: both; } } //noinspection CssOptimizeSimilarProperties @mixin linear-gradient($start-color, $end-color) { background-color: $start-color; background-image: linear-gradient(to bottom, $start-color, $end-color); } // Visibility // -------------------------------------------------- // Only shows hover on non-touch devices @mixin hover { .discourse-no-touch & { &:hover, &.btn-hover { @content; } } } @mixin ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } @mixin line-clamp($lines) { display: -webkit-box; overflow: hidden; text-overflow: ellipsis; word-wrap: break-word; -webkit-line-clamp: $lines; -moz-box-orient: vertical; -webkit-box-orient: vertical; } // // -------------------------------------------------- $vpad: 0.5em; $hpad: 0.65em; // for consistent sizing across inputs, buttons and dropdowns @mixin form-item-sizing { border: 1px solid transparent; font-size: var(--font-0); line-height: normal; box-sizing: border-box; padding: $vpad $hpad; .ios-device & { font-size: var(--font-size-ios-input); padding-top: $vpad * 0.8; padding-bottom: $vpad * 0.8; } } @mixin sticky { position: -webkit-sticky; position: sticky; } // Unselectable (avoids unwanted selections with iPad, touch laptops, etc) @mixin user-select($mode) { -webkit-user-select: $mode; user-select: $mode; } @mixin unselectable { @include user-select(none); cursor: default; } // Stuff we repeat @mixin post-aside { border-left: 5px solid var(--primary-low); background-color: var(--blend-primary-secondary-5); } // We still need -webkit for latest iPhone and Safari @mixin transform($transforms) { transform: $transforms; } @mixin appearance-none() { // resets default browser styles -webkit-appearance: none; -moz-appearance: none; appearance: none; } @mixin default-focus() { border-color: var(--tertiary); outline: 1px solid var(--tertiary); outline-offset: 0; } @mixin fa-rotate($degrees, $rotation) { transform: rotate($degrees); } /// Helper function to easily use an SVG inline in CSS /// without encoding it to base64, saving bytes. /// It also helps with browser support, especially for IE11. /// /// @author Jakob Eriksen /// @link http://codepen.io/jakob-e/pen/doMoML /// @param {String} $svg - SVG image to encode /// @return {String} - Encoded SVG data uri @function svg-uri($svg) { $encoded: ""; $slice: 2000; $index: 0; $loops: ceil(math.div(str-length($svg), $slice)); @for $i from 1 through $loops { $chunk: str-slice($svg, $index, $index + $slice - 1); $chunk: str-replace($chunk, '"', "'"); $chunk: str-replace($chunk, "<", "%3C"); $chunk: str-replace($chunk, ">", "%3E"); $chunk: str-replace($chunk, "&", "%26"); $chunk: str-replace($chunk, "#", "%23"); $encoded: #{$encoded}#{$chunk}; $index: $index + $slice; } @return url("data:image/svg+xml;charset=utf8,#{$encoded}"); } /// Replace `$search` with `$replace` in `$string` /// @author Hugo Giraudel /// @link http://sassmeister.com/gist/1b4f2da5527830088e4d /// @param {String} $string - Initial string /// @param {String} $search - Substring to replace /// @param {String} $replace ('') - New value /// @return {String} - Updated string @function str-replace($string, $search, $replace: "") { $index: str-index($string, $search); @if $index { @return str-slice($string, 1, $index - 1) + $replace + str-replace( str-slice($string, $index + str-length($search)), $search, $replace ); } @return $string; } // SCSS accepts HEX or RGB colors for rgba($color, 0.5) // CSS custom properties only accept RGB // Example usage: // --primary-rgb: #{hexToRGB($primary)}; // ... // rgba(var(--primary-low-rgb), 0.5) @function hexToRGB($hex) { @return red($hex), green($hex), blue($hex); } @function schemeType() { @if is-light-color-scheme() { @return "light"; } @else { @return "dark"; } } @function absolute-image-url($path) { // public_image_path is added by the stylesheet importer // it returns a CDN or subfolder path (if applicable). // SCSS will compile (and return the relative path) if public_image_path is missing. @if variable-exists(public_image_path) { @if (str-index("#{$path}", "/plugins") == 1) { $plugin_asset_path: str-replace($public_image_path, "/images", ""); @return url("#{$plugin_asset_path}#{$path}"); } @else { @return url("#{$public_image_path}#{$path}"); } } @else { @return url("#{$path}"); } } @mixin mention() { display: inline-block; // https://bugzilla.mozilla.org/show_bug.cgi?id=1656119 font-size: 0.93em; font-weight: normal; color: var(--primary); padding: 0 0.3em 0.07em; background: var(--primary-low); border-radius: 0.6em; text-decoration: none; }