Page MenuHomePhabricator

Move CSS signatures from body to html
Closed, DeclinedPublic

Description

Testcase

HTML5 allows class attributes on the root element. The CSS signatures (classes like "mediawiki ns-* page-* skin-*" etc.) that are currently applied to the body element could therefore be moved to the root element.

The advantage is that these signatures can then be used to style even the root element, which is currently impossible (see http://annevankesteren.nl/2004/08/signatures for the rationale; the post is about ID attributes, but still applicable).

This already works in every browser that allows styling the root element (IE >= 6 and all others) and even in IE 5.5 (which doesn't allow styling the root element, but still applies rules with selectors that start at the root element). Testcase attached.

Note, however, that this will break existing rules with unnecessarily specific selectors ("body.mediawiki" instead of just ".mediawiki"). It may therefore be wise to add the classes to both elements for a while.


Version: unspecified
Severity: enhancement

Attached:

Details

Reference
bz24915

Event Timeline

bzimport raised the priority of this task from to Low.Nov 21 2014, 11:05 PM
bzimport added a project: MediaWiki-Parser.
bzimport set Reference to bz24915.
bzimport added a subscriber: Unknown Object (MLST).

Well unnecessarily specific is a big word. Don't forget that <h2> id's can easily class with other elements, though for classes, it's applies a bit more (unless we are talking about specificity styling, to avoid having to use !important)

The main use case of these classes currently is serving as the start of a descendant selector in order to change things depending on the namespace or page name or skin (e.g. [[MediaWiki:Monobook.css]], [[MediaWiki:Print.css]] etc.). For this use case, it doesn't matter if the descendant is a body or a html or a div or whatever.

A secondary use case is increasing specifity. That is IMHO somewhat questionable as it mixes unrelated things, but that would still be possible, it just needs to be written differently (e.g. body.mediawiki becomes html.mediawiki or .mediawiki body).

Clashes are certainly possible, but when do they occur? Header IDs can clash with interface IDs just if the header text happens to be the same as an interface ID, but classes are different; I'm not aware of any place where user input is translated to a class name. Users could of course hand-craft things to clash with interface classes, but what's the point in that? Given the (IMHO unnecessarily specific) rule

body.page-Main_Page h1.firstHeading { display: none !important; }

that could just as well be

.page-Main_page .firstHeading { display: none !important }

they would have to hand-craft two class names just to get something not displayed. It's much easier to just add style="display: none;" to it.

Adding tag names for the purpose of avoiding clashes also doesn't scale very well. It incidentally works for body (but also html) because user can't add body and html tags, but fails with many other tags. On the other hand, omitting unnecessary tag names is sometimes recommended for performance reasons, see http://code.google.com/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors and https://developer.mozilla.org/en/writing_efficient_css.

The advantage of moving the classes to the root element is that users could, for example, put stuff with descendant selectors that start with .mediawiki into the user style sheets of their browsers (e.g. chrome/userContent.css in the Mozilla profile directory) in order to customize all MediaWiki installations at once, including the root element. I don't know how many people are actually doing that, but it's a useful thing to do and already possible, with the restriction that the root element cannot be styled this way.

ayg wrote:

Typically everything other than <body> is display: none anyway. Do you have some specific real-world use-case where you want to style something outside the <body>? If not, I don't see the point in paying the transition cost. Not only will people use body.page-Main_page selectors that will no longer work, they'll also probably do things like .page-Main_page { ... } expecting the rules to apply to <body> rather than <html>. If there's no clear real-world non-theoretical reason for it, I'd say WONTFIX.

(In reply to comment #3)

Typically everything other than <body> is display: none anyway. Do you have
some specific real-world use-case where you want to style something outside the
<body>?

Styling html and body is the only way to do things that can be done in Monobook with #globalWrapper (and Vector does not have a #globalWrapper), such as making a page narrower:

html {
background: white; /* needed to prevent body from filling the canvas */
}
body {
background: #f3f3f3;
margin: 0 auto;
width: 80%;
}

If not, I don't see the point in paying the transition cost. Not only
will people use body.page-Main_page selectors that will no longer work, they'll
also probably do things like .page-Main_page { ... } expecting the rules to
apply to <body> rather than <html>.

Whether rules apply to <body> or <html> does not make a difference in most cases. But now I see another problem: Page names can contain non-ASCII characters and non-ASCII characters must not occur before the charset has been declared. This would mean that the charset must be declared in the HTTP header (right now this is not strictly necessary because no non-ASCII characters occur before the <meta charset> element).

ayg wrote:

(In reply to comment #4)

Styling html and body is the only way to do things that can be done in Monobook
with #globalWrapper (and Vector does not have a #globalWrapper), such as making
a page narrower:

html {

background: white; /* needed to prevent body from filling the canvas */

}
body {

background: #f3f3f3;
margin: 0 auto;
width: 80%;

}

True.

Whether rules apply to <body> or <html> does not make a difference in most
cases.

It makes a big difference if some rules are applied to both elements, though, which will be the case if both have the classes during a transition period. So I don't see any way to switch the classes without a level of disruption that doesn't seem warranted by the benefits.

But now I see another problem: Page names can contain non-ASCII
characters and non-ASCII characters must not occur before the charset has been
declared. This would mean that the charset must be declared in the HTTP header
(right now this is not strictly necessary because no non-ASCII characters occur
before the <meta charset> element).

I think MediaWiki is careful to do this anyway, so this might not be a big deal.

Initial notes:

  • body.page-* is not unnecessarily specific, it's good practice to restrict signatures to the element signatures are placed on.
  • Admittedly charsets are not relevant, MediaWiki sanitizes any non-alphanumeric+-_ character in css classes.

Specific to this idea of fixed-width centering vector:

  • Here's a base for fixed-width centering vector https://www.mediawiki.org/wiki/User:Dantman/vector-fixed.css
  • Have you actually bothered to test out the technique you're describing on vector? The css you specified doesn't work it needs more to actually make vector fixed-width. And when you actually manage to make vector fixed-width you realize that it's messed up: The backgrounds need to expand to the full width of the page, but can't because of the hack added, the lack of a right border on #content looks messed up, but you can't add one the same way vector adds the left one without a second content area inside the content area or using css3 multiple backgrounds that only work in some modern browsers.
  • What you really want sounds like an enhancement to vector to provide wrapper elements with a class that can be used to make the actual content+ui of vector fixed-width.

I don't see a good enough reason to force users to migrate css breaking compatibility or maintain duplicate signatures. Please file the vector enhancements as a separate bug.