PremekBrada: ModularCSS

from Wiki KIVu

ModularCSS project/idea

The problem Cascading Style Sheets are a maintainability nighmare: they badly scale for large/complex sites, they use magic values instead of constants (so double maintenance problem occurs, e.g. consistently changing trivial things like colours across the website), they don't relate to page structure.

References:

Proposed solution

Approach Apply standard good engineering practices to CSS design and syntax. Enable and define clear consistent mapping to CSS 2.1 syntax so automated conversion is possible. Keep it as simple as possible.

A few additional constructs to modularize the sheets:

one-line comments -- enable // comments in addition to / */

Details are listed below.

One-line comments

Allow C++ style comments "from here to end of line".

Syntax: @@ <text> // <comment>

Example:

See the examples of other constructs below.

Mapping:

Clear -- remove "//", wrap comment in / / pair.

Multi-properties

Allow several properties to be listed in one rule.

Syntax: <property>, <property>, ... : <value>

Example:

  // hide text by color
  p.invisible {
    background, color: white;
  }

Mapping:

Clear: split into several rules with the same value for individual properties.

@param

Declares that the CSS expects an URI parameter. The parameter is then used as if it was defined via @define (see below). The default value must be defined for each parameter for cases when the stylesheet is not accessed by an URI.

Syntax: @param name(default)

Example:

 
  @param fg(black)    // parameter 'fg' with default value 'black'
  /* use: style.css?fg=red&bgcol=#d0d0d0 */

Mapping:

Replace param usage ($param) by the value.

@define and $value

Defines a constant token to use in rules. Token usage must not occur within the definition.

Syntax: @define name(value) to define, $name to use

Example:

  @define textfont(Times New Roman, serif)
  // ILLEGAL:
  @define bodyfont(Garamond, $textfont)

  body {
    font-family: $textfont;   // here the constant's value is substituted
    font-size: small;
  }

Mapping:

Replace token usage ($name) by the value.

@region

Creates a scope in the CSS that is related to a named block in HTML. The name of the region is a CSS selector consisting only of "id" or "class" HTML element attributes. Inside the @region declaration, regular rules can be used -- their selectors then apply only within the named HTML block. Region declarations cannot be nested.

Syntax: @region name { <properties> <rules> }

Example:

Assume the following HTML code:

<div id="menu">
  <ul>
  <li><a href="first">First option</a></li>
  <li><a href="second">2nd option</a></li>
  <li><a href="last">Last option</a></li>
  </ul>

  <ul class="admin">
  <li><a href="copy">Copyright</a></li>
  <li><a href="mailto:addr@domain.tld">Email us</a></li>
  </ul>
</div>

Then the following CSS can be defined:

@region #menu {

  background: silver;     // these apply to the #menu DIV
  color: black;
  font-size: small;

  ul { margin-left: 0; }  // scoped elements, as if #menu ul etc. selectors
  ul li { list-style: none; margin-left: 0; }
}

@region #menu .admin {
  li a, li a:visited { color: gray; }
}

Mapping:

Expand into a series of rules with the region name prepended to each selector.

@if blocks

Include part of stylesheet based on token value. Conditional blocks cannot be nested.

Syntax: @if (<condition>) { <rules> } [ @elsif (<condition>) { ... } ] [ @else { ... } ] where <condition> ::= $token | $token = value | $token != value

Possible extensions to this conditional are (1) use references to properties in condition (e.g. if (body.color = black) ... ) and (2) use regexp comparison in addition to the plain string equal/nonequal.

Example:

#footer {
  @if ($fg) {    // token "fg" is defined
    color: $fg;
  }
  @else {
    color: black;
  }
}

#page {
  background: white;
}
@if ($pgborder != none) {    // re-style also inner blocks if border is used
  #page { background: silver; border: $pgborder; }
  #page #menu { border: none; }
}

Mapping:

Include only that part of conditional sheet for which the condition holds.


Back to NametyPruzkumy (in Czech)

Retrieved from http://wiki.kiv.zcu.cz/PremekBrada/ModularCSS
Content last modified on 16 November 2005, 10:16