Problem/Motivation
Currently, language_css_alter()
checks every CSS file that is added to the page for it's -rtl.css counterpart and, if it exists, adds it as well. Due to CSS weight (the -rtl.css stylesheets are added after the original styles) the RTL rules override the LTR rules.
This is a total anti-pattern and pretty much a Drupalism. It requires you to maintain another file and keep it in sync with the changes in your main stylesheet. It involves PHP logic to dynamically detect and inject the right .css files on run-time including quite a few file_exists() checks for every page RTL page that is loaded.
It also makes it much harder to leverage Sass or any other preprocessor to automatically generate the RTL output in your stylesheets which would otherwise be a big win for maintainability.
Proposed resolution
Let's leverage the 'dir' attribute in our stylesheets. Basically, this would look like this:
// CSS
.foo {
float: left;
}
[dir="rtl"] .foo {
float: right;
}
// Plain Sass
.foo {
float: left;
[dir="rtl] &{
float: right;
}
}
// Or even with cool mixins that do all the magic for you
.foo {
// Mixin that inverts the float for RTL languages.
@include float(left);
}
This increases the maintainability of our stylesheets and makes them somewhat self-contained. It takes away the burden of synchronizing changes across multiple files when changing something as simple as a float.
Considerations
This slightly increases the size of the CSS for LTR pages aswell as both, the RTL and the LTR styles are served for everyone. However, it normally comes down to just a few lines of extra CSS that are even minified and compressed on production environments and therefore absolutely negligible.
Comment | File | Size | Author |
---|---|---|---|
#69 | 2015789-69.patch | 122.14 KB | echoz |
#68 | 2015789-66.patch | 121.54 KB | LewisNyman |
#68 | interdiff.txt | 2.71 KB | LewisNyman |
#63 | 2015789-63.patch | 119.42 KB | echoz |
#56 | 2015789-55.patch | 119.32 KB | rteijeiro |
Comments
Comment #1
Snugug CreditAttribution: Snugug commentedI one million perent agree with this. This is a terrible Drupal anti-pattern that must be stopped. In fact, the best practice in the wider world of the web is to do what's proposed (using the
dir
attribute selector). There is support back to IE7 for this and all major modern browsers. We already have everything in place to do this, we just need to make it the standard and update our CSS.Comment #2
fubhy CreditAttribution: fubhy commentedAnother bonus: Testing RTL styles without page reloads/constantly switching languages by simply changing the dir attribute in your favorite debugging tool.
Comment #3
ry5n CreditAttribution: ry5n commented+1 from me as well. The maintenance and testing advantages outweigh a few extra lines of CSS in the LTR stylesheet. Theoretically at least, primarily RTL themes could assume RTL and use [dir="ltr"] for the overrides.
Comment #4
sdboyer CreditAttribution: sdboyer commented@Snugug and discussed this a while back in the context of bringing in Assetic, and came to strong agreement that it should be chucked. big +1
Comment #5
ruplA separate RTL stylesheet is another HTTP request too. The proposed method of inlining RTL is the way to go.
Comment #6
Gábor HojtsyRe @rupl and others: the RTL sheet should not be a separate HTTP request. You are using CSS aggregation on your site, aren't you? I mean extra HTTP request maybe in development, but not on your live site?
@all: one of the selling points of the RTL sheet as a separate file is that those sites that will only ever appear in LTR will not need to pass on extra CSS selectors and potentially substantial more styling to the client that will never be needed on the site. This can be avoided with external CSS build tools that are not Drupalisms. I assume contrib themes will not rely on those either in the Drupal 8 cycle but I may be mistaken.
Either way, I'm fine getting rid of this Drupalism but more wider feedback would be great. Especially as this related to front end performance. As said I'm not at all concerned about HTTP requests, because you *do* have CSS aggregation turned on on your site. I'm concerned about the extra parsing overhead for unused selectors on LTR sites. We usually optimise Drupal for LTR/English first and try to avoid overhead on LTR/English sites if possible. I've been called out before on several occasions when introducing multilingual features/capabilities that taxed the original LTR/English base use case.
Comment #7
Gábor HojtsyComment #8
tsi CreditAttribution: tsi commentedYep.
What about adding a 'directionality' argument to drupal_add_css so if anyone wants they can achieve the same conditional loading without the overhead?
Comment #9
tsi CreditAttribution: tsi commentedstupid tags... sorry...
Comment #10
Gábor Hojtsy@tsi: I don't think making people work more to achieve the same in Drupal 8 can be solved as an improvement :D Also multiple conflicting ways to do the same does not make a consistent contrib space.
Comment #11
tsi CreditAttribution: tsi commentedWell, I do see a case where someone would like to add a separate stylesheet based on directionality (or language), it can already be done today but will require *a lot* more work, I'm suggesting that simplifying that (work less, not more) while removing language_css_alter() is an improvement while simply removing language_css_alter() might be seen as a regression in these cases.
Example use case: I have two fontello font sets that should be included based on directionality/language.
Comment #12
fubhy CreditAttribution: fubhy commentedOkay, but we are only talking about a handful of bytes here. All it would do, basically, is inverting floats, margins, paddings, border radius, etc. which is not that much. Also, due to things like Sass, with proper @mixins and @extends the footprint will be even smaller as many things can be aggregated into shared rules during preprocessing anyways. So yeah, we should not have to argue about a few bytes. Also, another downside of RTL stylesheets is that they require an additional CSS aggregation derivative which means that, when switching the language you have to re-download the entire package (granted, that should not happen very often but still, RTL stylesheets double the amount of hosted CSS aggregates).
Comment #13
tsi CreditAttribution: tsi commentedI do agree with @Gábor about the performance issue - on production, with aggregation enabled you're getting less lines of CSS today, whether it's a handful of bytes or more depends on the implementation.
A point to consider, if we do decide that those extra lines are negligible, is that inline RTL rules (right next to the LTR ones) will probably give us much more solid support for RTL css in core (it will simply be harder to neglect) and better maintainability. On the other hand, that will require a major change to almost all of core CSS - can this still be done for 8.x ?
Comment #14
LewisNymanI think we should be upfront about this and admit that this is a performance regression, and not an insignificant one. Before we start making assumptions about "just a couple of lines" can we verify the impact here?
Bartik alone has 320 lines of RTL CSS, compressed this weighs about 4KB. I haven't spent any time checking all the core or even contrib module RTL CSS.
Comment #15
LewisNymanI think we should be upfront about this and admit that this is a performance regression, and not an insignificant one. Before we start making assumptions about "just a couple of lines" can we verify the impact here?
Bartik alone has 320 lines of RTL CSS, compressed this weighs about 4KB. I haven't spent any time checking all the core or even contrib module RTL CSS.
Comment #16
fubhy CreditAttribution: fubhy commentedHoly moly there is a lot of crap in the stylesheets. I think this is going to serve us well in uncovering A LOT of RTL/LTR bugs in core. I found at least 20 spots where I could fix small bugs immediately and many more where the RTL styles are either completely missing or there are RTL styles for things that don't even exist anymore (sometimes even the selectors are no longer there).
Anyways... Here is a first patch.
Comment #17
fubhy CreditAttribution: fubhy commentedForgot a direct call to language_css_alter(). Urghs. Removing uglyness.
Comment #19
fubhy CreditAttribution: fubhy commentedAccidentely added a whitespace before <?php
Comment #20
fubhy CreditAttribution: fubhy commentedDuh... Removing a few merge relicts.
Head -> Table.
Comment #21
mortendk CreditAttribution: mortendk commentedyup the Drupalism's like this must die die die die die (die)
will argue for having those few X amount of lines (even if its a ton) is not gonna be an issue compared to the maintainability for the frontend.
Comment #22
fubhy CreditAttribution: fubhy commentedYes exactly. I can see this being a big win for maintainability of RTL styles as everything is self-contained and close together. So if you change a LTR style you directly see that there is a RTL style that has to be updated too.
Once this gets in I will open an issue to dig through all of core CSS to find missing RTL styles (I already saw quite a few while doing this patch... mostly paddings/margins as floats are more obvious apparently). This is really going to help with fixing Core CSS.
Comment #24
fubhy CreditAttribution: fubhy commentedAh, there you are RTL CSS test! Bye bye test!
Comment #25
fubhy CreditAttribution: fubhy commentedComment #26
Snugug CreditAttribution: Snugug commentedTo get back to the size issue, let's break down some actual numbers from properly optimized CSS (not CSS by committee). In creating a responsive grid system with five different grids ranging from 4 to 16 columns wide, the CSS for the grid system in LTR 7715 bytes. The total sum of all of the RTL components of the grid (mind you, this is a grid that can describe each and every single potential layout on the site) is 828 bytes. When talking about performance vs regression, while it may be technically true that if I were to serve the combined file to LTR it would be a regression of performance for LTR (by 828 bytes), in most frontender's estimation, the worse thing is what we currently have; different CSS packages per language direction. I'm going to go out on a limb and say that an extra 828 bytes for everyone and a solid CSS cache for all directions is better than two different CSS packages, one for each direction, of equal size plus a little more for the RTL direction.
Even if we were to take this to what Bartik currently has, what we're really talking about is an extra 4kb for everyone or an extra 44kb for RTL users. Now when talking performance and regression, which would you take?
Comment #27
tsi CreditAttribution: tsi commentedSam, I don't follow your argument, why would you assume an *extra* 44kb for RTL users?
Following your example the situation would be 40kb for LTR and 44kb for RTL pages - every page delivers what is needed for it to display properly, as it should.
Saying that, I do support the maintainability gain - as an RTL dev that had a lot of hard time bringing RTL into core, it is very hard to maintain and get patches committed when styles live in a separate file, mainly due to lack of public interest.
It feels weird to bring all the RTL css into the default stylesheets just because we couldn't maintain them, but we couldn't, so maybe we should.
Comment #28
LewisNymanThere's some flawed logic here, only the inverse styles from the LTR stylesheets are redundant for RTL to users. They still need every other line. Assuming the CSS matches line for line, it would be 4kb waste for LTR and a 4kb waste for RTL.
Comment #29
tsi CreditAttribution: tsi commentedJust for reference - probably one of the worst examples for RTL maintainability nightmare, would never happen if it would've been inline with the LTR styles; it took around 16 months to get Seven to support RTL, months after D7 was released we still had to deal with broken admin theme on RTL sites #766458: Seven theme lacks rtl styling
Comment #30
Snugug CreditAttribution: Snugug commentedThe 44k additional comes from multilingual sites switching languages needing to download an entire new CSS package for the RTL vs the LTR. It's only 4k if you're exclusively making an RTL site, but I was under the impressions we're talking about multilingual sites where language swapping is a possibility (and probability).
Comment #31
JohnAlbinI'm in favor of this change as well. But let's see some reviews now! :-)
Comment #32
fubhy CreditAttribution: fubhy commentedAs mentioned previously, this is basically a straight cut&paste patch except for the Views CSS where I could not match up certain things due to inconsistencies between the LTR and the RTL styles (due to them being outdates/incomplete). So the most important part to take a look at is the Views UI. Everything else really is just cut&paste including some minor fixes.
However, we really need follow-ups to look at all the stylesheets once more to identify missing RTL styles as I fear there are quite a few. Floats seem to be covered mostly, but so many paddings/margins/borders/etc. are not touched in the RTL styles and not marked as LTR styles in the stylesheets. Furthermore in some places when LTR for example sets a margin-left the RTL style sets a margin-right but without unsetting the margin-left. So, yeah... That definitely requires some follow-ups.
Anyways, for now I'd be happy for some reviews!
Comment #33
LewisNymanfubhy's patch/audit of RTL styles is enough to convince me that the current way of working is not effective. Mistakes using the current process have slipped through the review into core.
This new process will make it easier to implement, test, and review LTR/RTL styling. In the light of the inconsistencies fubhy has found, I think this is something we need, rather than something we want.
Performance should always be a consideration. looking forward towards Drupal 9, we'll start using modern CSS3 layout techniques that will remove or reduce the need for separate RTL styling.
Comment #34
LewisNyman#24: 2015789-24.patch queued for re-testing.
Comment #36
LewisNymanThe patch got knocked out of whack by commit
b3b93ac4246304d18984799a23add7cd7c1d5cdf
Comment #37
rteijeiro CreditAttribution: rteijeiro commentedPatch doesn't apply well with latest 8.x branch. Conflicts with the following files:
core/modules/system/css/system.admin.css
core/modules/system/css/system.admin-rtl.css
Maybe it needs re-roll.
Comment #38
echoz CreditAttribution: echoz commentedPlus openid module is now gone from core.
Comment #39
penyaskitoRerolled #36.
Comment #40
rteijeiro CreditAttribution: rteijeiro commentedRemoved OpenID module references.
Comment #41
echoz CreditAttribution: echoz commentedThe changes in system.admin.css committed in #1861702: Add a responsive grid to the Appearance page are not properly in #40 patch
Comment #42
echoz CreditAttribution: echoz commentedThis re-does system.admin.css and also adjusts tour.css since #1363112: Simplify names of "element-x" helper classes was committed.
Comment #44
echoz CreditAttribution: echoz commentedadded new change to vertical-tabs.css in #2018913: Vertical tab styling for tabs should not be applied when JavaScript is disabled and no tabs are present
tagging with awesome new tag!
Comment #46
echoz CreditAttribution: echoz commented#44: 2015789-44.patch queued for re-testing.
Comment #47
echoz CreditAttribution: echoz commentedtagging
Comment #48
rteijeiro CreditAttribution: rteijeiro commentedRe-rolled with the latest changes.
@echoz: How the "Avoid commit conflicts" tag works exactly?
Comment #49
echoz CreditAttribution: echoz commentedHeh, I only assumed this was helpful for the core committers when other rtbc patches exist that touch the same files, they can make the call to commit those first, rather than cause them to need re-rolls.
---
I didn't review all, but only caught the following typo while comparing the 2 latest patches.
views_ui.admin-rtl.css had ".views-display-columns > *" and when copied to views_ui.admin.css, it is mispelled as "[dir=rtl] .views-display-colums > *" (columns is missing the "n").
Were there other places that you hand typed rather than copy pasted?
Any tips how to review this beast?
Comment #50
JohnAlbinI'm reviewing this in detail now. But I see that you forgot to remove the core/themes/bartik/css/style-rtl.css file.
Comment #51
rteijeiro CreditAttribution: rteijeiro commented@echoz: I only fixed conflicts by hand in the following files:
core/modules/views_ui/css/views_ui.admin.css
core/modules/views_ui/css/views_ui.admin.theme.css
core/themes/seven/style.css
I know it was better to copy and paste but I thought there were less changes :(
Will try to re-roll this beast this afternoon but feel free if you want to do that.
Comment #52
JohnAlbinI checked every single selector in this patch.
And this patch should be RTBC after these changes:
[dir=rtl] form .field-multiple-table .field-multiple-drag .tabledrag-handle{
remove the
/* LTR */
.js[dir=rtl] .toolbar .tour-toolbar-tab.tab
to:.js[dir=rtl] .toolbar .bar .tour-toolbar-tab.tab
[dir=rtl] .views-display-colums > *
to:[dir=rtl] .views-display-columns > *
to:
to just below the
.password-suggestions ul li
ruleset.[dir=rtl] ul.primary li.active a{
[dir=rtl] html.js .vertical-tabs-panes
to:html.js[dir=rtl] .vertical-tabs-panes
Comment #53
rteijeiro CreditAttribution: rteijeiro commentedWorking on it ;)
Comment #54
fubhy CreditAttribution: fubhy commentedThanks for working on this, guys. Everyone++
Comment #55
LewisNymanI can't wait for this commit! Ping me if there's anything I can do to help.
Comment #56
rteijeiro CreditAttribution: rteijeiro commentedJust commited all the changes. Hope it's now RTBC ;)
Feel free to blame on me :P
Comment #57
echoz CreditAttribution: echoz commented*All* of JohnAlbin's changes listed in #52 have been implemented, nice work guys!
I jumped the gun and tested, patch applies cleanly, RTL language works, when this goes green it's RTBC for me.
Note: we need RTL admin testing, found lots of padding corrections needed.
Comment #58
echoz CreditAttribution: echoz commentedRTBC!
BTW, @JohnAlbin, this resolves #1997630: RTL stylesheets not recognized for vertical tabs
Comment #59
PanchoAt least this RTL override is missing in color.admin.css:
Also, would it be an option to explicitely use
[dir=ltr]
, so we wouldn't override the ltr rules for rtl, but would have either the ltr selector or the rtl one match?So instead of:
it would look like this:
This would make more obvious, which rules need (and have) an RTL counterpart and which ones are generic.
Don't know how it would work out performance-wise, though.
Comment #60
fubhy CreditAttribution: fubhy commented@Pancho: There are _many_ missing RTL styles. But this issue is not about fixing those. We are just moving what's already there. If we had to fix it all in here we would never get it done. Let's just get the straight conversion (from -rtl.css to [dir=rtl]) done and then clean up and fix the CSS somewhere else.
Setting back to RTBC (although I did not check the last patch).
Comment #61
rteijeiro CreditAttribution: rteijeiro commentedSure, in fact there are some CSS clean up issues here #1921610: [Meta] Architect our CSS
I'm moving them to the Drupal 8 Mobile Initiative sandbox as branch per issue: https://drupal.org/sandbox/johnalbin/1488942
Don't hesitate to comment that changes in the corresponding issue ;)
Thanks for the feedback.
Comment #62
echoz CreditAttribution: echoz commented#59 is correct that
is in and removed from color.admin-rtl.css but missing in color.admin.css
Comment #63
echoz CreditAttribution: echoz commentedAdded
to color.admin.css
Comment #64
rteijeiro CreditAttribution: rteijeiro commentedPatch applies well. Go for RTBC!!
Comment #65
JohnAlbinI double checked the latest patch. It has all the changes I requested plus the
[dir=rtl] #palette .hook
ruleset. This is RTBC from me as well.Comment #66
LewisNymanGood news: #1337554: Develop and use separate branding for the installer just landed.
Bad news: we need a re-roll.
Comment #67
rteijeiro CreditAttribution: rteijeiro commentedWorking on it :'(
Comment #68
LewisNymanComment #69
echoz CreditAttribution: echoz commented#68 missed 3 .task-list RTL rulesets from seven/style.css probably because the style-rtl.css hadn't dropped the ol qualified selector that had been dropped in style.css in the installer commit.
Comment #70
rteijeiro CreditAttribution: rteijeiro commentedPatch applies well. Go for RTBC!!
Comment #71
alexpottGreat work...
Committed bfba7b8 and pushed to 8.x. Thanks!
Comment #72
JohnAlbinWoo-hoo! Great work, everyone!
Comment #73
jessebeach CreditAttribution: jessebeach commentedPlease include the quotation marks when you write this attribute selector. We should be doing this as a standard. So.
Non-standard
Standard
Here's a good article explaining why we want to make this our standard: http://mathiasbynens.be/notes/unquoted-attribute-values
Although it is valid to leave out the quotes for values of an attribute that are alphanumeric, it can lead to problems for non-alphanumeric values and I'd rather just see everyone be in the habit of using quotations so it's not something we need to consider.
Comment #74
ry5n CreditAttribution: ry5n commentedYay! +1 to #73
Comment #75
rteijeiro CreditAttribution: rteijeiro commentedOkay, what do you suggest to fix this?
Maybe a new patch that replaces all
[dir=rtl]
sentences by[dir="rtl"]
?Comment #76
Gábor HojtsyI think a quick followup issue would be good.
Comment #77
echoz CreditAttribution: echoz commentedCreated followup #2030925: quote rtl attribute selector
Comment #78
jessebeach CreditAttribution: jessebeach commentedChange notice: https://drupal.org/node/2032405.
Comment #79
echoz CreditAttribution: echoz commentedRemoving "Needs change notification" tag.
Docs had been updated at CSS formatting guidelines
Comment #80
hass CreditAttribution: hass commentedhttps://drupal.org/node/1887862 is not clear that this is ONLY a D8 rule. D7 beginners will be confused.
Comment #81
echoz CreditAttribution: echoz commented#80, thanks @hass, docs now edited branching RTL for Drupal versions.
Comment #82
Gábor HojtsyThe RTL orientation of the sidebar somehow got lost between this issue and #1337554: Develop and use separate branding for the installer.
See: #2033137: New installer sidebar not properly RTL.
Comment #83
hass CreditAttribution: hass commentedAdded extra D6/D7 section to docs.
Comment #84
YesCT CreditAttribution: YesCT commentedIs the comment on the change notice https://drupal.org/node/2032405#comment-7637701 correct?
I thought the same thing, that /* LTR */ should be on things that need to have a RTL counterpart.
If the comment is right, we should update the actual change notice.
Comment #85
echoz CreditAttribution: echoz commented#84, yep and has been corrected, good catch.
Comment #86
Wim LeersAnother follow-up filed: #2085673: Remove all remaining "-rtl.css" references.