This stylelint-scss rule is useful because we were inconsistent when
using calc(); sometimes we added interpolation to Sass variables, and
sometimes we didn't. The reason why we originally added interpolation
was that it was necessary until we migrated to Dart Sass in commit
d54971e53. Since then, we can omit the interpolation, which is also what
the Sass documentation recommends [1].
[1] https://sass-lang.com/documentation/values/calculations/
The division operator `/` from Sass is deprecated because `/` is used in
CSS for uses other than dividing numbers. That's why we were getting
many warnings like:
```
Deprecation Warning: Using / for division outside of calc() is
deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($line-height, 2) or calc($line-height / 2)
More info and automated migrator: https://sass-lang.com/d/slash-div
margin-top: $line-height / 2;
```
Since using math.div makes the code harder to read and `calc` is
universally supported by all browsers (although the implementation in
Internet Explorer doesn't work in certain cases), we're using `calc`
when assigning the value to a CSS property.
However, we're also using divisions when assigning Sass variables, and
in those cases using `calc` is trickier because sometimes these
variables are used in other operations. We'll handle these cases in the
next commit.
The Web Content Accessibility Guidelines version 2.1 added a success
criterion called Non-text Contrast [1], which mentions that the focus
indicator must contrast with the background, and version 2.2 introduced
a specific one regarding focus appearance [2]. According to that
criterion, the focus indicator:
* is at least as large as the area of a 2 CSS pixel thick perimeter of
the unfocused component or sub-component
* has a contrast ratio of at least 3:1 between the same pixels in the
focused and unfocused states.
Our current solution for highlighting elements on focus has a couple of
issues:
* It doesn't offer enough contrast against the default white background
(1.6:1)
* It offers even less contrast against other backgrounds, like the
homepage banner or the featured proposals/debates
Making the color of the outline darker would increase the contrast
against these backgrounds, but it would reduce the contrast against
other backgrounds like our default brand color.
For this reason, most modern browsers use a special double outline with
two different colors [3], and we're choosing to combine an outline and a
box shadow to emulate it, using the brand color as the second color.
However, this double-colored outline doesn't work so well when focusing
on dark buttons surrounded by a light background, so instead we're using
a triple outline, which works well on any color combination [4]. Since I
feel that making the third outline 2px wide makes the overall outline
too wide, I'm making the inner outline just 1px wide since that's enough
to prevent edge cases.
Note that Foundation adds a transition for the `box-shadow` property on
`select` controls, which gets in the way of the focus we use on the
language selector. So we're removing the transition.
Also note that the box-shadow style didn't work properly with the
box-shadow we added on the `:hover` status on cards, so we're changing
the code in order to cover this case.
Finally, note that the box-shadow isn't displayed properly on multiline
links (in Chrome, not even with `box-decoration-break: clone`), like the
ones in debates/proposals/polls/investments/processes titles, so we're
changing the style of these links to `inline-block`.
[1] https://www.w3.org/TR/WCAG21/#non-text-contrast
[2] https://www.w3.org/TR/WCAG22/#focus-appearance
[3] https://www.sarasoueidan.com/blog/focus-indicators/#examining-(current)-browser-focus-indicators-against-wcag-requirements
[4] https://www.erikkroes.nl/blog/the-universal-focus-state/
We were using each one half the time, while they both had the same value
by default. It was impossible to know when me meant "use a dark color
here" or "use the secondary brand color" here.
So now we're only using one variable, so it's easy it'll be easy to add
CSS custom properties to overwrite this variable. We're choosing
`brand-secondary` because its name makes it less problematic to use a
light color.
This way we simplify the code a bit.
Note we're only using this function when variables for background colors
are already defined, since that means customizing the variable using the
background color will automatically change the color of the text.
Customization isn't easier when using raw colors.
We were defining (for instance) white text against the `$brand`
background. That meant that, if somebody customized the `$brand` color
so it used a light color, they had to customize the text color as well
in order to guarantee proper contrast between text and background
colors.
So we're using `color-pick-contrast` instead, which means we don't have
to manually calculate whether white or black will be the color which
makes the text more readable.
This way we remove duplication and it'll be easier to add better support
for RTL languages.
In a few years this might not be necessary since support for the `gap`
property in a flexbox layout will improve. At the time of writing,
however, only 86.5% of the browsers support it [1].
[1] https://caniuse.com/flexbox-gap
We weren't using a global maximum width for the <body> element because
we wanted the background of some elements to cover the whole screen. If
the body didn't cover the whole screen, then we would have to find a way
to extend the background beyond the limits of the body.
Elements can take the whole screen width using a width of 100 viewport
width (vw) units, which weren't as widely supported when CONSUL
development started as they are today.
However, there's a gotcha will vw units; they don't take into account
the vertical scrollbars browsers add when scroll is needed. That means
that an element with a width of 100vw would cause a *horizontal*
scrollbar when the vertical scrollbar appears on the screen. So
approaches like this one wouldn't work:
```
body {
margin-left: auto;
margin-right: auto;
max-width: $global-width;
}
@mixin full-background-width {
&::before {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
}
```
We could add `overflow-x: hidden` to the body to avoid the horizontal
scrollbar. However, on certain screens sizes that could cause some
content to disappear if there isn't enough horizontal space for all the
elements.
If we tried some other solution based on using `max-width` with `margin:
auto` on the <body> element, it would result in a body having a fixed
width and a variable margin (depending on whether there's a scrollbar).
So it wouldn't be possible to set a negative margin on child elements
based on the margin of the body, because that margin would be different
depending on the existence of a scrollbar.
So, instead, we're adding a fixed margin to the body, which depends on
the viewport width and the font size of the <html> element. With this
approach, when a vertical scrollbar appears, the margin of the <body> is
still the same; what changes is its width. That means we can set a
negative margin on child elements based on the margin of the <body>. No
horizontal scrollbar will appear.
Note we're slightly duplicating the code by using two variables
(`$body-margin` and `$full-width-margin`) to do the same thing. We could
simply use `$body-margin` and then use `calc(-1 * #{$body-margin})` in
our `full-width-background` mixin. We aren't doing so because some old
versions of the Android browser and Internet Explorer can't handle this
operation. Since our whole layout is based on these properties, in this
case supporting old browsers is quite important.
For similar reasons we're using a breakpoint instead of using the
`max()` function like: `Max(0px, calc(50vw - #{$global-width / 2}))`. At
the time of writing, `max()` is only supported in about 91% of the
browsers.
With this change, we no longer need to add `row` elements to make sure
we don't exceed the maximum width; the <body> element takes care of
that.
Also note banners sometimes have a full background and sometimes they
don't, depending on which page they appear. We're adding specific rules
for them.
Finally, the code for full width borders is a bit brittle; sometimes we
want the border to cover an element, and sometimes we don't. For
example, we had to slightly change the way the border of the "tabs" in
legislation processes is rendered. Without these changes, the borders
wouldn't overlap as we intended. We also had to add a `z-index` to
navigation links so their bottom outline is visible when they're
focused. The recommendations have a border with the same color as the
background so it's painted on top of the border of the `help-header`
section.
We're using `background: #fff` and `background: $white` in many places.
Sometimes we mean "use the same background as the body", which means if
we change the body background so it's, let's say, dark, we'll also have
to change all these places.
So now we're using `$body-background` in more places, so changing the
general background color is easier.
There are still some places where we use `#fff` or `$white`. Sometimes
it's hard to tell whether the intention is "use a white background here"
or "use the same background as the body here". When in doubt, I've left
it the way it was.
Just for testing purposes, I've tested locally how things would look
like if we added this code to `_consul_custom_overrides.scss`:
```
$body-background: #fea;
$card-background: $body-background;
$tab-background: $body-background;
$tab-content-background: $body-background;
$table-background: $body-background;
```
Or:
```
$body-background: #333;
$text: #fcfcfc;
$body-font-color: $text;
$card-background: $body-background;
$tab-background: $body-background;
$tab-content-background: $body-background;
$table-background: $body-background;
```
Testing shows we've still got a long way to go to make it easy to add
custom color themes, since there are many custom colors in the code.
Hopefully these changes bring us one step closer.
Using `inherit` is IMHO more expressive since it means "use the color of
the parent element".
This is particularly useful for CONSUL installations using custom
styles. Consider the following code:
```
h2 {
color: $white;
a {
color: $white;
}
}
```
If we'd like to customize the way headings look, we'd have to override
two colors:
```
h2 {
color: $red;
a {
color: $red;
}
}
```
Consider the scenario where we use `inherit`:
```
h2 {
color: $white;
a {
color: inherit;
}
}
```
Now we only need to override one color to change the styles:
```
h2 {
color: $red;
}
```
Setting the color to `$white` or `#fff` while setting the background to
`$brand` is a pattern we were using in many places. Since we're going to
edit it in order to fix the `::selection` behavior, we're defining the
pattern in one place.