The elements were given a minimum width of `rem-calc(240)` (that is,
15rem). Considering one element is double the width of the other one,
that means that in screens between 40rem and 45rem there would be a
horizontal scrollbar.
Adding a `flex-wrap: wrap` property fixes the problem. We're also using
`flex-basis` to guarantee a minimum width and make one element be double
the size of the other one when they're on the same line. No need to add
breakpoint rules due.
Finally, we're adding an artifitial gap between flex elements so we can
remove the `@include grid-col` rules.
In the case of the public layout, the row element was originally there
so the content of the top links had a maximum width. Since now the body
has that maximum width, we no longer need the row element.
In the other layouts I guess the row elements were added because there
were float elements inside them. We can use a flexbox layout instead and
these elements are no longer necessary. This also makes the layout more
robust when there isn't enough space on one line for both the language
selector and the external links.
Note we're using `flex-grow: 1` to make one element appear on the left
of the screen and the other one on the right. It would be easier to use
`justify-content: space-between`. However, there's a bug in Internet
Explorer and old versions of Firefox; they include the
absolutely-positioned `::before` element we use to set the full width
background when calculating where to position the elements. The bug was
fixed in Firefox 52 (released in 2017).
These element had no columns inside and the row classes had only been
added to give them a maximum width. That's no longer necessary since now
the body has that maximum width.
We were using these rules in order to set the maximum width of an
element to `$global-width`. However, since we now do so in the <body>
element, there's no need to apply these rules to "rows".
Note we're adding `overflow: hidden` to the budget subheader. That's
because it only contains `float` element inside, and we're now missing
the `.row::before` and `.row::after` rules which make sure float
elements are rendered properly.
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.
Note that in order to simplify the component tests (which for some
reason seem to be whitespace-sensitive), we have to omit whitespace
characters inside the `<option>` tags.
Also note we're simplifying the test with a missing language name; since
a component test doesn't involve a whole request, we don't need a
complex setup (I'm not sure we even need it in system tests).
The `<optgroup>` doesn't make much sense if all options are inside one
group. And the information provided was redundant: when using a select
field having "Language" as a label, it's obvious that the options are
the available languages.
Now that, since now the `<select>` field is smaller, we need to add an
extra padding so the icon doesn't overlap the text.
There are two bugs in Internet Explorer which caused our footer to be
rendered incorrectly.
First, the `flex: 1` property doesn't work so well when `flex-direction`
is set to `column`. We're replacing it with `flex-grow: 1`. No need to
set other `flex-basis` nor `flex-shrink` in this case since in this case
the default values will work just fine.
Second, it didn't handle the body height being set to `100%` so well,
and the footer was rendered after that 100% point, even if the content
still continued.
So we're using `min-height` instead, which is actually a bit more
accurate (since the body is usually taller than the document root
element). This causes a different issue since on IE the `flex-grow: 1`
property becomes useless. This will only affect IE users with very large
screens, though, and it's way better than rendering the footer
overlapping the main content, so we can live with that. The page won't
look as great as in other browser, but it will still be usable.
This way it's possible to customize these colors by just changing a
variable.
The code is now quite a bit hacky; since I'm not an expert in color
design, I didn't want to change the colors we were using in case it made
the application have less appeal.
If slightly changing these colors isn't a problem, we could use
Foundation's defaults to simplify the code, maybe just changing the
`$table-color-scale` variable.
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.
These elements already inherit these background colors form their parent
elements. Defining them explicitly makes it harder to change them and it
also makes it harder to customize the styles in other CONSUL
installations.
Using `currentcolor` is IMHO more expressive, since it shows the
intention of styling the border with the same color as the text.
This is particularly useful for CONSUL installations using custom
styles. Consider the following code:
```
.is-active {
border: 1px solid $brand;
color: $brand;
}
```
If we'd like to customize the way active items look, we'd have to
override two colors:
```
.is-active {
border: 1px solid $brand-secondary;
color: $brand-secondary;
}
```
Consider the scenario where we use `currentcolor` (which is the default
border color):
```
.is-active {
border: 1px solid;
color: $brand;
}
```
Now we only need to override one color to change the styles:
```
.is-active {
color: $brand-secondary;
}
```
Since we are using the same color as the text color in both the public
and admin areas, we can omit the border color completely. Since now
admin elements get the exact same border, we can remove this border so
they'll inherit the same border as used in the public area.
Since we're only changing the style of the border in one case and the
color in the other case, we don't have to duplicate the code for every
property.
This makes it easier for other CONSUL installations to customize these
borders.
By default Foundation uses a `#1779ba transparent transparent`
transparent border. We were overriding the whole border, when we only
needed to override the top border. Furthermore, we were overriding it
twice: once in the public area and once in the admin area. However, if
we use `currentcolor`, we only have to override it once, and in both
cases the border will have the same color as the text surrounding it
(white in the public area and black in the admin area).
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;
}
```
Since commit dcec003d0 we're only using the menu-text class in the admin
layouts. So instead of defining styles for menu-text and then
overwriting them in the admin section, we can define them just in the
admin section.
Since we don't have <img> tags in the menu-text element in the admin
section, we can remove their styles. And we can also remove the styles
we were overriding twice (like `line-height`).
As mentioned in the previous commits, a `<select>` field which submits
its form on change causes many accessibility and usability issues, so
we're replacing it with the order links we use everywhere else.
Since the links "Id" and "Title" by themselves don't have enough
information to let users know they're used to sort by ID or title, we
have to update them somehow. We could add a "Sort by:" prefix before the
list of links (and associate it with the `aria-labelledby` attribute);
however, we don't do this anywhere else and might look weird depending
on the screen size.
So we're simply adding "Sort by" before each link.
Now that we don't use the `wide_order_selector` partial anymore, we can
remove it alongside the styles for the `select-order` class.
We use order links in many places in the web. However, in the comments
section and the list of community topics, we were displaying a
`<select>` element, and changing the location when users select an
option.
This has several disadvantages.
First, and most important, it's terrible for keyboard users. `<select>`
fields allow using the arrow keys to navigate through their options, and
typing a letter will select the first option starting with that letter.
This will trigger the "change" event and so users will navigate through
a new page while they were probably just checking the available options
[1]. For these reasons, WCAG Success Criterion 3.2.2 [2] states:
> Changing the setting of any user interface component does not
> automatically cause a change of context unless the user has been
> advised of the behavior before using the component.
Second, the form didn't have a submit button. This might confuse screen
reader users, who might not know how that form is supposed to be
submitted.
Finally, dropdowns have usability issues of their own [3], particularly
on mobile phones [4]
The easiest solution is to use the same links we generally use to allow
users select an order, so using them here we make the user experience
more consistent. They offer one disadvantage, though; on small screens
and certain languages, these links might take too much space and not
look that great. This issue affects pretty much every place where we use
order or filter links, so we might revisit it in the future.
Note we're moving the links to order comments after the form to add a
new comment. In my opinion, having an element such as a form to add a
new comment between the element to select the desired order of the
comments and the comments themselves is a bit confusing.
[1] https://webaim.org/techniques/forms/controls#javascript
[2] https://www.w3.org/WAI/WCAG21/Understanding/on-input.html
[3] https://www.youtube.com/watch?v=CUkMCQR4TpY
[4] https://www.lukew.com/ff/entry.asp?1950
"Is it related content? Yes (link) No (link)".
After reading that, you probably haven't decided whether to click the
"Yes" link or the "No" link or neither of them. You probably have to
read the content it's related to, and then go back to these links.
That's the reason we style them so they're on the right of the screen on
languages which are read from left to right, so first we read the
content and then we read the links to mark it as related or unrelated.
So it makes sense to put these links after the content they refer to.
This way users with small screens as well as screen reader users will
also see/hear these links after they get the proper context. It will
also be more intuitive for keyboard users, who saw the focus on the
links before focusing on the title of the related content, when they
probably expected the opposite.
Since we're now using a flexbox layout instead of a right float, this
also means the content will automatically be shown on the left when
switching the content direction to "right to left".
We were only showing these actions to users with small screens and to
mouse users on hover. Keyboard users or users with a touch screen of a
medium or large size could never find out the actions were there.
The button looked just like regular text and it wasn't obvious that it
was an interactive element.
So we're styling it like the "Hide" link (which should actually be a
button, by the way).
Note buttons by default don't have a `cursor: pointer` property because
they're usually styled in a way that makes it obvious they're
interactive elements. Since that isn't the case here, we're adding that
extra hint for mouse users.
Also note all these links/buttons will look like regular text to color-
blind users. And if they use a touchscreen, they won't be able to hover
on them to see the cursor change. We might need to change these elements
in the future.
The button was announced as expanded when the form was hidden and as
collapsed when the form was shown.
This is because Foundation sets the expanded attribute based on whether
the class to toggle already exists. Since initially the form had the
"hide" class and the button toggled that class, Foundation checked that
the class was already present and so set the button as expanded.
So we're changing the toggler class for a class we don't use at all,
just so Foundation initiall sets `aria-expanded=false` and then changes
it to `aria-expanded=true` after the button is clicked. Then we're
ignoring this class completely and are styling this form with CSS
instead.
We could also use a toggler class like "visible" and write something
like:
```
.add-related-content + form:not(.visible) {
display: none;
}
```
However, using ARIA attributes is more robust as it guarantees the
styles will always be in sync with what screen reader users experience.
And we could also remove all the Foundation toggler functionality and
use our own JavaScript to handle the button state. We might do so in the
future.
This way the relationship between the two elements is more obvious. And
since now the button and the form are siblings, it's easier to find one
based on the other using CSS or JavaScript.
Nowadays there are many users with a screen of 1920px (or higher) width
but who don't change their font-size preferences and keep them at 16px,
which is the default in most browsers.
On pages which use the whole window width, that results in unreasonably
long lines which are very hard to read. That's the main reason why many
sites (including CONSUL) use rules like `max-width: 75rem` for the body
or other elements.
However, on extra large screens this causes the content to be in the
middle of the screen while most of the screen is empty, and the text
might also be too small for that resolution, making it harder to read.
There are a few approaches to solve this problem.
Using just viewport units like `font-size: calc(4vw + 4vh + 2vmin);` is
indeed responsive, but it's got an important flaw: it ignores user
preferences, and so the font size will be the same for users who prefer
a 16px size and for users who prefer a 32px size.
Using `calc(1em + 0.2vw)` or similar might make the text too big on
small screens.
Finally, using `max(1em, 1vw)` would work in a similar way to what we're
doing, but zooming in and out would only work when the viewport width is
less than 100em (at that moment, 1em == 1vw).
So we're taking an approach where zooming in and out always works at
least to a certain degree (due to the 0.25em part) and the font size is
increased gradually when we reach the point where the viewport width is
bigger than 100em. We're using 0.25em since it will be exactly 4px with
the default browser configuration, and so calculations are easier than
with (for example) 0.3em.
Disclaimer: I've tested this feature on several devices with different
screen sizes and resolutions, but I must admit there might be cases I'm
unaware of where there are side effects for certain combinations of
screen size/resolution/dpi. In general, though, the side effects should
be similar to what happens when users increase the font size in their
browser's preferences.
Note we're using `Max` instead of `max` because Sass can't handle the
CSS `max` function, as mentioned in commit cdfa23fc6.
When the "Or fill the following form" text was translated to another
language or customized by administrators, the text could span over two
lines. Since the element had a fixed height, it could overlap with the
text below it.
So now we're using an element with a relative position to achieve the
same effect (have the contents of the elements on top of its border).
This way we make it more obvious that it's clickable and, since adding a
border requires adding padding, we increase the touch area, making it
easier to use and more accessible for users with motor disabilities.
Since now the button looks like a button, we don't need the pointer
cursor Foundation adds to hamburger icons and can use the default cursor
browsers provide for buttons.
Some users might not be able to touch the icon due to a motor
disability. Other users might think the "Menu" text is part of the
button and try to touch it instead.
Making the "Menu" text part of the button makes it easier to show/hide
this menu. Besides, it lets screen reader users with a small screen hear
the word "Menu" associated to the button.
We could simplify the HTML a bit more but Foundation's `hamburger` mixin
uses the `::after` element with `position: absolute`, so we can't apply
it directly to the button without making the CSS more complex.
Using `currentcolor` and `color: inherit` is IMHO more expressive (we're
saying we want to use the same color as the text) and makes it easier to
customize these colors in other CONSUL installations. We also remove
duplication as we can use the same styles for both the admin and the
public layouts.
On small screens, sometimes the bottom of the footer didn't have the
footer's background color.
I'm not sure why the `min-height` rule affects this outcome. However,
since this rule usually results in footer with quite a bit of empty
space at the bottom, we can simpliy remove the rule and use padding to
guarantee there's a bit of space between the text in the footer and the
bottom of the screen.
Using `<a>` tags with no `href` means these elements cannot be activated
by keyboard users, so we're replacing them with buttons.
In the future we probably want to add more consistency so all toggle
buttons use the same code. We might also add styles depending on the
`aria-expanded` property.
Since we were defining the selection to have the same text color and
background color as the element they were in, it resulted in the
selection being invisible.
It wasn't that noticeable because we were using this color combination
mainly in links and buttons, and selecting their text is not as common.
But we plan to use the `$brand` color on budget headers as well, and
this issue is more obvious there.
Browsers like Chrome weren't that affected because they automatically
make the selection semi-transparent and so the selected text still had a
slightly different color. In order to prevent this effect when the
selection is white, we're using a 0.99 opacity (in this case Chrome
ignores numbers higher that 0.998).