Ben Ward

CSS3 Proposal - !required properties and styles

.

This was posted to the CSS public mailing list (www-style) today.

It’s a proposal for the forthcoming CSS3 specification that would put an end to ‘browser sniffing’ in the future and allow web designers to embrace new and very powerful CSS techniques while more easily providing simpler presentation for older browsers.

It would be a valuble aid, especially when a new specification as large as CSS3 is to be launched. I’d be most greatful if CSS authors would take the time to read it and consider the value in the use-cases I’ve cited and any of your own.

Feedback on the proposal should really be sent to the

www-style at w3 dot org
mailing list, but I welcome more general comments in the Blog as well, just please remember that a comment here is unlikely to be heard by the CSS Working Group, while a post to the mailing list is more likely.

I’ve recently developed a site in which the lower levels of navigation (lists) are hidden until a parent (a <li>) is :hover’d over. The effect (commonly called “Pure ”Cascading Style Sheets">CSS Menus") is nice. A degraded, CSS1 supporting version is provided in the same stylesheet by using CSS2 selectors (namely “>”) to hide the newer content from old browsers. However, when testing using Konquorer 3.1.4 (the latest version you can get running on Windows+Cygwin, not actually the current version at all) I discovered a problem.

This version of KHTML supports the “>” selector, so applied the collapsed menu styles, but didn’t support :hover on all elements. Thus, the menus displayed collapsed, but the UA was unable to show the content when hovering.

The CSS spec does not require UAs to only implement complete specs
(else we’d still be without CSS1…) but when support of the same level of CSS varies in a UA, I would like to avoid resorting to any kind of JavaScript sniffing to more finely control implementation. It extends development time in terms of otherwise unnecessary research and adds to the workload of maintenance over a period of years for the site’s lifespan.

Hence, this proposal, (which comes in two parts).

1) Introduction of a “!required” declaration. This would be added to the CSS syntax in the same way as the “!important” declaration is used at the moment. It could be specified on a property-by-property basis, or to entire styles.

e.g.
foo {
  background-color: #F00;
  vertical-align: bottom !required;
}

In the above style, for a user-agent to apply the style it must support all properties marked as !required. If a UA does not support vertical-align (as in this example) then it should not apply background-color either.
Conversely, if it did not support background-color but did support vertical-align, then the style should be applied as normal with the property not marked as !required unrendered.

A larger example:
foo.watermark {
  display: none;
}

foo.watermark {
  display: block;
  position: absolute;
  bottom: 0;
  right: 0;
  opacity: 10% !required;
}

In this case, we have an element foo (which lets say is an image that the author wants used as an overlaying watermark on their site).
However, if the UA doesn’t support the CSS3 opacity property, then the watermark could obscure the content of the page and make it unusable.
The first style hides it completely from all UAs, and the second
should only be implemented by a UA that understands opacity. Thus, the author has no worries about his content being obscured by presentation.

Part 2) A way of declaring ‘groups’ of styles and requiring entire styles within a group. In my original use case, the problem arose from an unimplemented :hover style. However, this was a different style altogether from that which was responsible for transforming the menu into its initial, collapsed state. It’s that collapsing rule that needs to be ignored if :hover is not implemented, not the :hover rule itself (or any property within it).

I have a less solid idea about how to declare this syntax, so consider this as a starting point only.
/* a group of styles */
@group {

  /* the first style in the @group */
  foo bar {
    display: none
    background-color: #0F0;
    color: #000;
  }

  /* the second style in the @group - this is required */
  foo:hover bar !required  {
    display: block;
    position: absolute;
    top: 0px;
    left: 1em;
  }
}

In this example, a child element will only be displayed if its parent is hovered over. However, the :hover rule is marked as !required.
Should the UA not understand the :hover rule (or if that rule fails as a result of any contained property that is also marked as !required) then everything within the @group should be ignored (therefore bar will not be hidden, and some other styles elsewhere could specify a degraded presentation).

For my own use-case: The CSS for displaying the lists as pop-up menus would be wrapped within a @group { } and failure on a li:hover rule would also fail everything related to the collapsed menu system and not make the content inaccessible.

N.B.

  1. If a style is marked as !required and is not contained within a @group, then the entire stylesheet should fail and be ignored.

  2. If a style is marked as !required, and contains a property that is marked as !required which then fails, then the entire style should fail.

This !required syntax would allow a user-agent to perform a ‘self assessment’ on what to apply, rather than any grotesque system of conditional styles based on software name (c.f. Microsoft’s conditional comments extension to HTML).

I see no reason why !required could not also be applied to a @group (@group !required { ... }) and have the same failure inheritance applied to it as any other property & style relationship.
Whether nesting @groups would be taking the idea too far away from the interests of keeping a simpler syntax I don’t know.

Feedback is greatly appreciated, but it would be best sent to the w3c CSS mailing list.

You can file issues or provide corrections: View Source on Github. Contributor credits.