Closed jonathanmoore closed 6 years ago
@jonathanmoore you're correct in that the replacement solution would be to use Liquid colour filters:
<style>
:root {
--color-body-text: {{ settings.color_body_text | color_modify: 'red', 255 }};
--color-main-background: {{ settings.color_main_bg | color_lighten: 30 }};
}
</style>
We could continue to add to this list of available filters. Besides a colour contrast filter, are there any other filters that would be useful for you to replace SCSS functionality?
This is a larger issue with using custom properties with SCSS.
There is currently no way, from what I see, to use custom properties inside of SCSS functions/mixins. I learned this the hard way, and it now makes sense why it doesn't work as expected. An example I ran into was the vertical rhythm implementation (using the Plumber Sass library): https://github.com/Shopify/starter-theme/issues/1. I'm going to keep thinking about this 🤔.
I am completely stumped on a solution to fit basic and common SCSS functionality into the new concept of CSS variables. Here is a scenario where our current and future themes that will not work with the new version of Slate:
@function get-color-accent-text($color) {
@if (lightness($color) > 50) {
@return #000000;
} @else {
@return #ffffff;
}
}
$color-accent: {{ settings.color_accent }};
$color-accent-text: get-color-accent-text($color-accent);
In working with Slate 1.0.0 beta there does not seem to be a way to pull off any {% if %}
logic, and we are limited to long chains of filters. Here is what I attempted, however on deploy the assign values from snippets/css-variables.liquid
are not available in the generated .css.liquid file.
{%- assign color_accent_lightness = settings.color_accent | color_brightness | divided_by: 255 | times: 100 -%}
{%- if color_accent_lightness > 50 -%}
{%- assign color_accent_text = '#000000' -%}
{%- else -%}
{%- assign color_accent_text = '#FFFFFF' -%}
{%- endif -%}
--color-accent-text: {{ color_accent_text }};
To take it even further, we have plans to improve the contrast for accessibility by using the YIQ color space which provides better results over brightness. http://dannyruchtie.com/color-contrast-calculator-with-yiq/ https://medium.com/@MikeKellyWeb/calculating-color-contrast-with-sass-eff39ef23f96
Perhaps this would be a good example for a new liquid color filter...
Input: #7AB55C
{{ '#7AB55C' | color_contrast }}
Output: #000000
Input: #F33D6A
with manually overwriting the dark and light value
{{ '#F33D6A' | color_contrast: dark: '#222222', light: '#DDDDDD' }}
Output: #DDDDDD
I still there was a way to preserve some basic SCSS that could be rendered by Shopify's servers. Being able to run the theme's dynamic settings through logic is quite helpful.
More information to expand this issue beyond color example...
When relying on CSS variables to locally compile SCSS files for development or production, Sass will fail to build if you apply any operations to Sass variables assigned by CSS variables.
settings_schema.json
setting for a base font size, base_font_size
, with values ranging 15px-20px.<style>
:root {
--base-font-size: {{ settings.base_font_size }};
}
</style>
$base-font-size: var(--base-font-size);
body { font-size: $baseFontSize; }
h1 { font-size: $baseFontSize * 2; }
$base-font-size: var(--base-font-size);
@function em($target, $context: $base-font-size) {
@return ($target / $context) * 1em;
}
body { font-size: $base-font-size; }
h1 { font-size: em(28px); }
ERROR in ./assets/styles/theme.scss
Module build failed: ModuleBuildError: Module build failed:
font-size: $base-font-size * 2;
^
Undefined operation: "var(--base-font-size) times 2".
Researching into the use of CSS variables along with Sass, it seems like you would have to use calc()
. I don't know if there is a good workaround that isn't going to feel like a big hack. Overall this seems like it would have a big negative impact on the usefulness of Sass.
Trying to fit a complex theme into the current CSS vars approach would result in several hundred lines of code to chain together liquid assigns and filters, css vars and scss variables.
Update - we shipped some more Liquid color filters!
Now understanding where Slate is heading with CSS Vars, I have finally reworked our theme code to fit into the concept of Slate. I just wanted to follow up and document some details in case anyone else runs into similar challenges.
In general Slate will not allow for SCSS processing or manipulation of theme settings values. This is something we have taken advantage of in the past, so I had to approach processing colors, font sizes, etc from a different direction. Now we are using Liquid to manipulate colors or sizes and pass it along directly to the CSS vars. I see this approach as having two advantages:
Here are the two ways I'm now solving the examples detailed above...
{%- assign color_light_contrast = '#ffffff' -%}
{%- assign color_dark_contrast = '#000000' -%}
{%- comment -%}
Color - Primary Accent Text
{%- endcomment -%}
{%- assign color_r = color_primary_accent | color_extract: 'red' -%}
{%- assign color_g = color_primary_accent | color_extract: 'green' -%}
{%- assign color_b = color_primary_accent | color_extract: 'blue' -%}
{%- assign color_y_r = color_r | times: 0.299 -%}
{%- assign color_y_g = color_g | times: 0.587 -%}
{%- assign color_y_b = color_b | times: 0.114 -%}
{%- assign color_y = color_y_r | plus: color_y_g | plus: color_y_b | divided_by: 255 -%}
{%- if color_y >= 0.5 -%}
{%- assign color_primary_accent_text = color_light_contrast -%}
{%- else -%}
{%- assign color_primary_accent_text = color_light_contrast -%}
{%- endif -%}
The theme's settings allow for a choice of 16px to 20px as the base font size (body size), and then we are using REM or EM throughout the style to alter the size for various use. However, we wanted to offer a theme setting where merchants could control how large or small heading font sizes are. Rather than assigning pixel values for the headings, the values range from 0.75
to 1.5
. Then the theme's CSS will use calc()
to multiply the default heading REM size by the setting value.
<!-- css-variables.liquid -->
<style>
:root {
--typography-body-size: {{ setting.typography_body_size }}; // 16px to 20px
--typography-heading-size: {{ setting.typography_heading_size }}; // 0.75 to 1.5
--typography-base-line-height: 1.5rem;
--
}
</style>
// theme.scss
$typography-body-size: val(--typography-body-size);
$typography-heading-size: val(--typography-heading-size);
$typography-base-line-height: val(--typography-base-line-height);
@mixin calc-font-size(
$font-size: $typography-body-size,
$line-height: $typography-base-line-height,
$size: 1
) {
font-size: calc(#{$font-size} * #{$size});
line-height: calc(#{$line-height} * #{$size});
}
html {
font-size: $typography-body-size;
}
body {
font-size: 1rem;
line-height: $typography-base-line-height;
}
h1 {
@include calc-font-size(2.5rem, 3rem, $typography-heading-size);
}
h2 {
@include calc-font-size(2rem, 2.5rem, $typography-heading-size);
}
are there any other filters that would be useful for you to replace SCSS functionality?
Using css vars you cannot modify opacity like you previously could rgba($colorHighlight, 0.35)
.
Would this be something that would require a liquid filter now? Or is there a more obvious approach that I am missing?
I'm not sure I understand the full benefits of using css vars as opposed to scss vars.
@ButsAndCats There is a liquid filter that would take care of that example...
{{ settings.color_highlight | color_modify: 'alpha', 0.35 }}
Although the current version of Slate still is missing the ability to pass along usable assigned liquid variables. Solution in the works https://github.com/Shopify/slate/issues/541
Here is another example for adaptive colors by using color filters
src/snippets/liquid-variables.liquid
{%- capture color_btn_primary_focus -%}
{%- assign color = settings.color_button -%}
{%- assign color_brightness = color | color_brightness -%}
{%- if color_brightness <= 26 -%}
{{- color | color_lighten: 25 -}}
{%- elsif color_brightness <= 64 -%}
{{- color | color_lighten: 15 -}}
{%- else -%}
{{- color | color_darken: 10 -}}
{%- endif -%}
{% endcapture %}
src/snippets/css-variables.liquid
{%- include 'liquid-variables' -%}
<style>
:root {
--color-btn-primary-focus: {{ color_btn_primary_focus }};
}
</style>
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Problem
With the new workflow of defining
css-variables.liquid
that are then imported into a theme's SCSS file, it currently is not possible to utilize any SCSS color functions. Hypothetically this would apply to all other SCSS functions/mixins that need to be applied to values from the theme editor.snippets/css-variables.liquid
styles/theme.scss
Error:
More Information
Obviously this one basic example could be rewritten to use basic Liquid color filters in the
css-variables
file. More complex color functionality like checking for brightness on a background color and setting an a11y contrast compatible text color would result in very complex liquid