Spin-off from #3080100: Assess accessibility of Claro in High Contrast AKA forced colors mode.
Problem/Motivation
Problem 1: High Contrast issues
Claro has many CSS background images. These are stripped out by Internet Explorer and Firefox, but Edge displays them.
When Windows high contrast themes were originally introduced, IE and Firefox policy was to strip out all CSS background image, on the assumption that they interfered with the legibility of text that was on top of them. Early versions of Edge did this too, but later Edge changed the policy to display background images, but enforce a plain background in places where text was on top of a background image.
Some of these icons may include essential information. In those cases they can't be background images.
Some suggestions mentioned:
If any of these icons are essential, we should not use CSS background images.
Alternative techniques are to use SVG-in-HTML, or use CSS
content: url()instead of background images.A gotcha of not using CSS background image, is that you lose the other useful background properties like position (sprite images) and size, so workarounds are needed for those.
Problem 2: inlining concerns
From #3085245: Un-inline SVGs in pcss.css files, add build tool to inline them when compiled. Among other things, the issue states
That'd make it much easier to inspect the SVGs, to apply SVG optimization tools, to encourage reuse, etc. It also allows us to decide whether we truly want to inline these as data: URIs, or whether it makes more sense to let them be loaded by HTTP requests. This particular CSS file is 24 KB ungzipped and unminified. That's … a lot. Most of that is due to these inlined SVG files (this CSS file is the single largest CSS file in Claro).In other words: for developer ergonomics and for web performance optimization reasons I think we should consider changing this.
Problem 3: Not inlining concerns
Not inlining makes reuse easier and can potentially reduce filesize of the files doing the inlining. However, it also removes the ability to easily change color, which means a new file/request is needed for each color change of the same shape.
Problem 4: SVG Spritemap problems
#3020422: Toolbar style update Attempted to use SVG spritemap and discovered (comment #49)
Unfortunately: Firefox, IE11 and Edge are downloading the SVG sprite as many times as it is referenced with a different fragment id. And since the sprite SVG is obviously bigger than the singe SVG file, this is a huge performance penalty.
Problem 5: There are drawbacks to Icon Fonts as an option
See comment #16
Proposed resolution
See #16, #18, and #20 for results from exploring different approaches.
Based on the research, there is no approach that would be able to cater all use cases. The proposal is to use background: url() and request svg images, but add a postcss plugin to convert the url() calls to data uris whenever possible. Doing this in the build stage maintains the SVGs auditability/reuseability while still providing the benefits of inlining.
In cases where that isn't an option, be it animation or icons that must be visible in high-contrast, exceptions can be made but should be accompanied by a comment stating why.
Remaining tasks
- Move icons from CSS background image to CSS content.
- Figure out how to manage size, position, etc.
User interface changes
More robust cross-browser support for icons in Windows high contrast.
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | firefox-mac.png | 351.58 KB | justafish |
| #24 | firefox-linux.png | 68.11 KB | justafish |
| #11 | Снимок экрана 2019-09-30 в 19.12.12.png | 33.05 KB | kostyashupenko |
Comments
Comment #2
andrewmacpherson commentedComment #3
fhaeberle@andrewmacpherson Do you agree on the approach in this patch for icons?
Basically it's what you suggested but with the adding of a
colorandfill='currentColor'https://www.drupal.org/project/claro/issues/3083048#comment-13270936
Anyway, sprites are not useable and positioning gets harder with this approach.
Comment #4
andrewmacpherson commentedThere's no patch in #3.Oh, you meant a patch in another issue.Almost, but not quite. I'll test that patch first, then come back here and start notes for a general approach.
Comment #5
andrewmacpherson commentedComment #6
fhaeberleThank you! Looking forward to.
Comment #7
andrewmacpherson commentedminor edit, remove empty list item
Comment #8
huzookaI still feel that since Claro uses monochromatic icons, we will have an icon font in the end...
Comment #9
andrewmacpherson commented#8: icon fonts are a possibility for sure. There is a slight problem that CSS content is exposed to assistive tech, and this sometimes results in problems where a TTS tries to pronounce the character; but it's intended as a decorative image. Icon fonts are OK so long as they are applied to a
<span aria-hidden="true">.Comment #10
kostyashupenkoActually the problem here is not only with TTS. Main problem is that iconic font impossible to use for inputs. Only possible with pre-defined value attribute, which is wrong solution. Ex:
<input type="submit" value="">This problem solves by adding new tags and wrappers with absolute positioning.
Comment #11
kostyashupenkoGood and fresh idea will be to use svg-sprite and svg use + shadow dom technic: same way it was done on https://www.mass.gov
Please have a look on docs here https://www.npmjs.com/package/svg-sprite
Advantages:
1. Sprite can be cached by browser.
2. Icons are building immediately on page load without waiting for styles.
3. It is fully customizable on css side. (sizes, fill color and other properties are available)
Disadvantages:
1. This technic is not supported by IE, but it's possible to use polyfill for that https://www.npmjs.com/package/svg4everybody
Now few words about usages:
1. We keep config for svg-sprite (https://www.npmjs.com/package/svg-sprite) package in `scripts` folder (for example in json format)
2. We keep svg icons in `images` folder
3. We keep inners of svg icons as simple as possible, for ex:
4. We define path to svg sprite in .theme, like
5. Now you can use it from anywhere, for example twig:
or js:
or preprocess:
6. package.json (just an example)
7. call `yarn icons` or whatever else.
Profit.
Comment #12
fhaeberleLately we agreed (in our weekly drupal slack meeting – channel #admin-ui) to do a comparison table for the different icon / svg approaches to get a better overview. That would be really helpful because there are various options to consider.
Comment #13
huzookaYou can test the latest patch of #3020422: Toolbar style update.
This was my experience with SVG sprites:
See #3020422-49: Toolbar style update.
Comment #14
bskibinskiJust to chime in with the icons discussion.
If accessibility is big point for Claro, iconfonts are not the way to go, there are many caveats with this technique:
And these are just the accessibility issues/concerns, if you want to support more modern things, responsive icons, animated icons, or just simply multi-color icons, or changing the color of one part of the icon, then iconfonts are not a good choice.
They can't be responsive in one file. They don't support native animations, etc.
Also the web is moving towards icons in SVG, so contributors would be more comfortable to edit/update/create SVG's icons. Making iconfonts in a "good" way is a bit more tricky, and could hold people back to help out.
@hazooka I've been using SVG sprites for a pretty long time now, and have never noticed SVG icons are blurry on EDGE or IE11, do you have an example, i'm curious what could cause this.
The loading is pretty bad though, didn't notice that in my sites, I'll do some more research.
I would really recommend trying to go for SVG (sprites). The sprite loading problem will only occur in FF en IE11 (edge is moving to chromium very soon). And FF will fix this, just leaving IE11. But I could live with a little bit slower IE11 if modern browsers would work better. (opinion).
Comment #15
andrewmacpherson commented#14 is good accessibility advice.
In particular, the scenarios where the author-specified fonts don't get used are a indeed a very big problem. If the icon font is using the unicode private-use codepoints, the user's preferred font will likely not have the intended glyphs. This situation isn't just hypothetical; it's something that users commonly do in the real world.
Some icon fonts are moving away from the private-use unicode codepoints, to put their glyphs at standard codepoints. In theory it could mitigate the problem; the author-specified font doesn't get used, but the user-specified font has a glyph at that code point. But it's not safe to rely on this, because there is no way of knowing what fonts the user has. It might work if the user has the entire set of Noto font files, say.
This part isn't correct though (emphasis mine):
In cases where you need to convey the meaning of the icon, that's exactly what you want. Text alternatives are intended for all users who don't get the image. WCAG doesn't care how you implement images, or their text alternatives. If we were using
<img src="foo.png" alt="foo">, and users turned off images (to save data transfer, say) then the text alternative would be displayed. Text alternatives for CSS icons should behave the same way.Comment #16
bnjmnm@wimleers detailed his thoughs on Icon fonts in an early D8 toolbar issue #1963886: Use HiDPI icons in the toolbar
The arguments favoring icon fonts are pretty strong, but Wim pointed out several reasons they are probably not suitable for Toolbar. That said, it may be possible to find a solution that leverages icon fonts in a way that addresses these concerns, or the policy may need to exclude toolbar.
Pasting what Wim said here because we have too many tabs open already.
Requirements (for a Toolbar icon approach)
Approaches
Approach 1: "icon font"
, and with a
@font-facedeclaration for.iconfontso that the inserted character uses the icon font.Approach 2: "modules define their (SVG) icons; modules and themes can override them; build CSS dynamically"
.svgfile per icon). We could then automatically generate a single CSS file with all icons embedded as data URIs (like #52 already says, but using URI encoding).However, a side-effect of this approach is that we need some sort of hook or
.ymlto indicate which icons this module provides. How else can Drupal know how to generate that CSS file? It's less than ideal that we need another "metadata thing", this time for icons, but at the same time that is also utterly essential.How else will modules be able to override existing entries? How else can a theme override only Drupal core's default icons as well as the icons for modules a and b, and still have the system serve up the default icons for modules x and y?
A contrib module could then *still* override the default CSS generator and generate an icon font instead. Or a site-specific theme could override the default icon CSS file and embed its own optimized icon font.
............
Also, I'm converting this to a broader SVG related issue to avoid us simultaneously working on several SVG related issues only to discover the solutions conflict with one another. I'm choosing to make this one the central one as the most has been discussed here. I did update the issue summary, but still tagging "needs issue summary update" as it could use a bit more.
Comment #17
bnjmnmComment #18
bnjmnmAfter reading through this and issues covering similar territory, here's what I can gather so far regarding some of the options presented:
Icon Fonts
Despite having many appealing benefits... Between the accessibility issues documented in #14 and the concerns I quoted from @wim-leers in #16, this does not seem like a feasible option.
Icon fonts: Not an option (unless the concerns in #14and #16 can all be addressed)
SVG Sprites
Edge has switched to Chromium, so the multiple requests issue would impact Firefox (3.28% usage) and IE11 (1.44% usage). 4.72% isn't a huge number, but significant enough that SVG sprites would require enough other benefits to justify
#14 mentions that "Firefox will fix this" regarding the SVG sprite multiple-loading problem. I looked the issue and if you filter out the "is this still active" comments, the last activity on this issue was 6 years ago https://bugzilla.mozilla.org/show_bug.cgi?id=1027106. Perhaps @bskibinski is aware of progress not documented in the issue, but based on what I could find it doesn't seem like a fix is imminent.
Maintainability is another concern, particularly for modules like Toolbar that encourage icons from contrib modules extending it.
SVG sprites: Probably not unless there's a strong enough argument to justify the performance hit on 4.72% of browsers.
The remaining choices?
In a hypothetical situation where my assessment is correct and we can rule out SVG sprites and icon fonts, these are the remaining things I can think of that would need to be considered:
This seems too short a list for the amount of discussion...
Open to hearing why Icon fonts or Sprites should remain in consideration.
Comment #19
bnjmnmAdded several related issues with conversations covering similar territory.
Comment #20
bnjmnmHere's my take
Based on:
- The many similar conversations had about this topic
- The multiple-request bugs with SVG Sprite
- The accessibility issues with icon fonts
- The difficulty in auditing / reusing inline SVGs
My proposal is to - whenever feasible - use background: url() and request svg images, but add a postcss plugin to convert the url() calls to data uris. Doing this in the build stage maintains the SVGs auditability/reuseability while still providing the benefits of inlining.
In cases where this isn't an option, be it animation or icons that must be visible in high-contrast, exceptions can be made but should be accompanied by a comment stating why.
Comment #21
lauriiiGood job on making a summary of the previous discussions @bnjmnm!
It seems like there are strong arguments that go against using icon fonts and SVG sprites. While the extendability issues could be overcome, it seems like there are also some accessibility concerns in particular with the icon fonts approach #14. We can reconsider SVG sprites once the performance issues have been resolved in Firefox and IE 11.
It doesn't seem like any of the assessed approaches would be perfect. It seems like the best solution is to continue on the path that we have already taken. I'm glad that we identified that we can resolve some of the concerns by moving SVG icons to individual files and inlining them with PostCSS.
Let's open a follow-up for adding the PostCSS plugin for inlining the SVG images.
Comment #22
bnjmnmDid a small IS change to an earlier issue, and that can serve as the PostCSS plugin issue #3085245: Un-inline SVGs in pcss.css files, add build tool to inline them when compiled
Created one for high contrast mode tasks #3130305: Ensure all of Claro's background images are visible in forced colors mode.
Comment #24
justafishI can't reproduce that Firefox cache issue in neither Firefox for Linux (75) nor Mac (76.0.01)
https://justafish.github.io/sprite-test/
https://github.com/justafish/sprite-test
Comment #25
bnjmnmThe example in #24 also works fine for me in Firefox. The Firefox bug is documented here https://bugzilla.mozilla.org/show_bug.cgi?id=1027106 and still open, I'm unsure if this means the bug was fixed in a different issue or there's an implementation difference.
Comment #26
bnjmnmConfirmed it is still an issue and it is specific to fragments in css background images https://bbenjamin.github.io/bnjmnm/. One request on not-FF, three requests in FF. (yes, the SVG I quickly used to test doesn't have fragments in it, but the presence of a fragment identifier replicates the issue regardless).
Even if there was a postcss solution that used something other than fragments to access parts of a sprite (not sure if this exists...), our current plan to auto-inline svg css background images will similarly reduce requests.
Comment #27
ambient.impactI've been using SVG sprites inlined as
<use>which reference an SVG file with icons defined as<symbol>s for a few years now after looking at all the pros and cons of the various solutions. While I'd have preferred to use a pure CSS solution, I think that approach loses a lot of flexibility, especially the ability to recolour and transform icons. You can see my icon system on my site, which I use from the more obvious (Drupal, GitHub, and GitLab logos in the content; the social icons at the bottom) to less so (the drop-down menu arrows). More extensive use can be seen on my snippets page.Specifically to this discussion, back before migrating to Drupal 8, I heavily altered the Drupal 7 backport of the toolbar (a.k.a. the Navbar project), which you can see in this comparison video I made. Note how the new icons (on the second site) can have transform transitions and have no loading on hover/focus because it's just recolouring the existing icon, not loading anything new. The code itself for that project was pretty hacky, so I'd love to see some sort of proper, extendable way to alter the icons and provide our own implementation, if possible, but I'd very much recommend the inlined
<use>method. If you're curious about my Drupal 8 system, you can find it in my GitHub repo.Comment #28
lauriiiUpdated the issue summary with the conclusion. We can also remove the needs followup tag because the followup was opened in #22.
Comment #29
lauriiiI think we have given people enough time to provide feedback on this, especially given that we're not proposing that significant of a change at all. Usually, decisions like this would be posted on g.d.o but in this case it might not make sense given that we're just making a decision to continue more or less what we have done before. Let's focus next on #3085245: Un-inline SVGs in pcss.css files, add build tool to inline them when compiled.
Comment #30
lauriiiUpdating credits
Comment #32
mherchelAdding a comment here for posterity that the
content: url()technique does not work for Chromium versions of MS Edge (or really any Chromium browsers).In my opinion the easiest method is to use
mask-image. Note that this isn't supported under IE11, but we can do this with Drupal 10.Example:
https://codepen.io/mherchel/pen/PoEbxeR