Accueil / How we architected the CSS for Views on D7

How we architected the CSS for Views on D7

Let's just make one thing clear at the outset. Views is big. It's big like an aircraft carrier and it's big like Lebowski. If you use Drupal, you probably also use Views. Updating Views to D7 was no small task. Acquia, in an effort to update the UI of Views and integrate it into DrupalGardens, sponsored a code sprint in San Jose, CA at the end of February 2011. The sprint achieved more than any expected, due in major part to the effort of those who participated, both in person and remotely. Merlinofchaos describes the sprint in more detail and gives props to the folks made the sprint a success.

So back in February, when I (remotely) joined the folks on the Views sprint in San Jose, I had one goal in mind: get the CSS architecture right. I kvetch and tweet a lot about CSS in Drupal modules.  Sometimes a little too enthusiastically. But kvetching isn't coding. And at the end of the day, code is gold. 

For the CSS in Views, I went back to a proposal by Jacine Rodriguez: The Future of CSS in Drupal. In it, Jacine describes a method of breaking apart CSS declarations into files that target:

  • The basic implementation of a module
    • positioning and layout, if any is needed
  • Presentation styling
    • colors, fonts, border, backgrounds
  • Styles needed to style to or override a specific theme
    • Seven, Bartik, Garland or Stark
  • Styles needed to style to or override another module

Laying out the files

This is the approach we took in Views. So instead of a monolithic stylesheet or a few arbitrarily divided stylesheets, we ended up with many highly-targeted sheets.

In the image above, you'll see basic structure stylesheets (views.css, views-admin.css), theming stylesheets (views-list.css, views-admin.theme.css), module-targeted stylesheets (views-admin.contextual.css, views-admin.advanced_help.css, views-admin.ctools.css) and theme-targeted stylesheets (views-admin.seven.css, views-admin.bartik.css, views-admin.garland.css, views-admin.stark.css).

Structure vs. presentation styling

For this post, I'll focus on the admin CSS structure. First we have views-admin.css and its corrollary view-admin-rtl.css. This file was kept as slim as possible. As development continued over the course of a week in our sprint, this file was touched less and less often. As we established the basic layout components and their placement, it became less necessary to make edits to these styles. 

The screenshot above is a look at my editor (Espresso) for the views-admin.css file. Note at the top, the declaration for .views-displays .secondary .action-list. This declaration places the list items in the desired part of the interface. It does not include any information about color, text formatting, borders or backgrounds. This kind of presentation styling was placed in the views-admin.theme.css file, developed against the Stark theme, shown below.

In the screenshot above, you'll see presenation styling for the .views-displays .secondary .action-list li elements in the .views-admin.theme.css file. Why break up the styling like this? Well, the intent is to make the process of theming a module easier for future theme, module and distribution developers. When structure styling is mixed together indiscriminantly with presentation styling, any attempt to develop a new look-and-feel or to even make small changes, becomes a frusturating battle of CSS precedence and inevitably, !important modifiers on individual properties - the nuclear option from which there is no recourse.  

When presentation styling is contrained in a seperate stylesheet, a developer can simply knock out that sheet and proceed styling without losing the structural framework of the module. By structural framework, I mean the styling that makes the module usable, not beautiful

In reality, this separation is difficult to maintain. At times it may feel arbitrary. Here a couple questions I grappled with and how I answered them.

  • "Is the side padding part of the structure or part of the theme?".
    • In the case of columns, it was part of the structure, since padding is part of the box model and I needed to reach 100% when adding the widths of the columns in a grid
    • In the case of buttons, padding make them look pretty, but they'll work without it.
  • "Is this border part of the structure or part of the theme?"
    • In the case of one button from the jQuery UI, the border was used to calculate the width of the object. Border is part of the box model width calculation. So in the structural CSS, I had to set the border of .views-ui-dialog .ui-dialog-titlebar-close to 1px solid transparent to keep the button from jumping around on hover.
    • In the case of the views display settings buckets, borders were considered styling flare and were added to the theme.css file.

Even though the separation of structure from presentation is difficult to maintain, this does not excuse us as themers from making every effort to make these distinctions. As soon as we let our resolve buckle, we introduce a seed of muddle that turns any stylesheet is a raging mess of competing precedence and tangled cascade.

Theme-targeted stylesheets

Now, in the ideal development process, we would have built the module in Stark and layered in the presentation styling for Seven, Garland and Bartik secondarily. But I'd be rewriting history if I made the claim that's how we worked. In reality, we developed in Seven and made everything look gorgeous in Seven. Then someone had the bright idea to load a Views admin screen in Bartik, leading to these issues: Bartik, Garland, Stark

What did we do? We moved all of the Seven-specific styles into views-admin.seven.css with this patch. It took hours and it was painful. But it was the right thing to do. Once that was complete and Stark was made to look decent, styling Bartik and Garland took less than a couple hours. And now Views is ready for any other admin theme's particular styling.

Rather than loading all of these stylesheets, merlinofchaos came up with a clever bit of code that gets the active admin theme and loads the stylesheet for it specifically.

// Add in any theme specific CSS files we have
$themes = list_themes();
$theme_key = $GLOBALS['theme'];
while ($theme_key) {
  $list[$module_path . "/css/views-admin.$theme_key.css"] = array(
    'group' => CSS_THEME,
  );
  $theme_key = isset($themes[$theme_key]->base_theme) ? $themes[$theme_key]->base_theme : '';
}

And it works with child themes as well.

Module-targeted stylesheets

For modules, we took the same approach, loading the stylesheets only when the module is enabled:

// Views contains style overrides for the following modules
$module_list = array('contextual', 'advanced_help', 'ctools');
foreach ($module_list as $module) {
  if (module_exists($module)) {
    $list[$module_path . '/css/views-admin.' . $module . '.css'] = array();
  }
}

Admittedly, this approach is a bit hard-coded. What I would like to see in D8 is an extension of the drupal_add_css and drupal_add_js functions that provide an option for optional inclusion of stylesheets based on the current theme and module configurations.

The module-targeted stylesheets are fairly small, with views-admin.advanced_help.css weighing in at a mere 25 lines.

The temptation here is to simply put these few lines into views-admin.theme.css. Resist this temptation. These declarations concern a very specific module that may or may not be enabled on a user's site. Mixing these styles into the Views base styling would create implicit dependencies between these modules.  The only reason we get away with such muddling is because CSS let's us. Nothing will fail if we write sloppy CSS, except perhaps our resolve when we're fixing bugs or styling themes later. Think of your fellow themer. Give them good, clean CSS and the favor will be returned in the karmatic economy that is Drupal. 

Did we get it right?

Well, we got really close.  Really, really close. I'm extremely proud of our efforts to architect the CSS properly and then stick with it through a frenzied week of development. We've put a great example out there for others to follow.

Still, I have issues I'd like to improve in this and future modules.

  1. The declarations in views-admin.css are still highly specific. I'd like these to be more abstract. For instance the .views-displays-columns > * selector should really be replaced with a gridding system. Preferably one used throughout Drupal, just as we adopted jQuery as our JavaScript library in core.
  2. Some of the styling in views-admin.theme.css is still in the style of the Seven theme. It's difficult to bring a module down to basic, unstyled foundation. Some styling feels crucial to the presentation of information, like borders around sections so that the eye can distinguish them.  This tension between styling purity and usability may never be resolved satisfactorily.
  3. As I mentioned above, the logic for including theme- and module-specific stylesheets should be moved to Core, otherwise every module is going to solve this problem in a slightly different way. Cacheing and performance will most likely suffer.

This experience architecting the stylesheet structure for Views has given me valuable insight into the refactoring work that we must champion for D8. In Core, structure and presentation styling are mixed together across various modules. Jacine and others have started this cleanup effort. As we start updating modules to fit this cleaner file pattern, we'll have a better idea of how we're to straighten out the Core styling layer.

acquia
drupal planet

Ajouter un commentaire

Plain text

  • Aucune balise HTML autorisée.
  • Les adresses de pages web et de courriels sont transformées en liens automatiquement.
  • Les lignes et les paragraphes vont à la ligne automatiquement.

Filtered HTML

  • Use [acphone_sales], [acphone_sales_text], [acphone_support], [acphone_international], [acphone_devcloud], [acphone_extra1] and [acphone_extra2] as placeholders for Acquia phone numbers. Add class "acquia-phones-link" to wrapper element to make number a link.
  • Pour publier des morceaux de code, entourez-les avec les balises <code>...</code>. Pour du PHP, utilisez. <?php ... ?>, ce qui va colorier le code en fonction de sa syntaxe.
  • Les adresses de pages web et de courriels sont transformées en liens automatiquement.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <h4> <h5> <h2> <img>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
By submitting this form, you accept the Mollom privacy policy.