function drupal_add_css

You are here

7 common.inc drupal_add_css($data = NULL, $options = NULL)
5 common.inc drupal_add_css($path = NULL, $type = 'module', $media = 'all', $preprocess = TRUE)
6 common.inc drupal_add_css($path = NULL, $type = 'module', $media = 'all', $preprocess = TRUE)

Adds a cascading stylesheet to the stylesheet queue.

Calling drupal_static_reset('drupal_add_css') will clear all cascading stylesheets added so far.

If CSS aggregation/compression is enabled, all cascading style sheets added with $options['preprocess'] set to TRUE will be merged into one aggregate file and compressed by removing all extraneous white space. Preprocessed inline stylesheets will not be aggregated into this single file; instead, they are just compressed upon output on the page. Externally hosted stylesheets are never aggregated or compressed.

The reason for aggregating the files is outlined quite thoroughly here: http://www.die.net/musings/page_load_time/ "Load fewer external objects. Due to request overhead, one bigger file just loads faster than two smaller ones half its size."

$options['preprocess'] should be only set to TRUE when a file is required for all typical visitors and most pages of a site. It is critical that all preprocessed files are added unconditionally on every page, even if the files do not happen to be needed on a page. This is normally done by calling drupal_add_css() in a hook_init() implementation.

Non-preprocessed files should only be added to the page when they are actually needed.

Parameters

$data: (optional) The stylesheet data to be added, depending on what is passed through to the $options['type'] parameter:

  • 'file': The path to the CSS file relative to the base_path(), or a stream wrapper URI. For example: "modules/devel/devel.css" or "public://generated_css/stylesheet_1.css". Note that Modules should always prefix the names of their CSS files with the module name; for example, system-menus.css rather than simply menus.css. Themes can override module-supplied CSS files based on their filenames, and this prefixing helps prevent confusing name collisions for theme developers. See drupal_get_css() where the overrides are performed. Also, if the direction of the current language is right-to-left (Hebrew, Arabic, etc.), the function will also look for an RTL CSS file and append it to the list. The name of this file should have an '-rtl.css' suffix. For example, a CSS file called 'mymodule-name.css' will have a 'mymodule-name-rtl.css' file added to the list, if exists in the same directory. This CSS file should contain overrides for properties which should be reversed or otherwise different in a right-to-left display.
  • 'inline': A string of CSS that should be placed in the given scope. Note that it is better practice to use 'file' stylesheets, rather than 'inline', as the CSS would then be aggregated and cached.
  • 'external': The absolute path to an external CSS file that is not hosted on the local server. These files will not be aggregated if CSS aggregation is enabled.

$options: (optional) A string defining the 'type' of CSS that is being added in the $data parameter ('file', 'inline', or 'external'), or an array which can have any or all of the following keys:

  • 'type': The type of stylesheet being added. Available options are 'file', 'inline' or 'external'. Defaults to 'file'.
  • 'basename': Force a basename for the file being added. Modules are expected to use stylesheets with unique filenames, but integration of external libraries may make this impossible. The basename of 'modules/node/node.css' is 'node.css'. If the external library "node.js" ships with a 'node.css', then a different, unique basename would be 'node.js.css'.
  • 'group': A number identifying the group in which to add the stylesheet. Available constants are:

    The group number serves as a weight: the markup for loading a stylesheet within a lower weight group is output to the page before the markup for loading a stylesheet within a higher weight group, so CSS within higher weight groups take precendence over CSS within lower weight groups.

  • 'every_page': For optimal front-end performance when aggregation is enabled, this should be set to TRUE if the stylesheet is present on every page of the website for users for whom it is present at all. This defaults to FALSE. It is set to TRUE for stylesheets added via module and theme .info files. Modules that add stylesheets within hook_init() implementations, or from other code that ensures that the stylesheet is added to all website pages, should also set this flag to TRUE. All stylesheets within the same group that have the 'every_page' flag set to TRUE and do not have 'preprocess' set to FALSE are aggregated together into a single aggregate file, and that aggregate file can be reused across a user's entire site visit, leading to faster navigation between pages. However, stylesheets that are only needed on pages less frequently visited, can be added by code that only runs for those particular pages, and that code should not set the 'every_page' flag. This minimizes the size of the aggregate file that the user needs to download when first visiting the website. Stylesheets without the 'every_page' flag are aggregated into a separate aggregate file. This other aggregate file is likely to change from page to page, and each new aggregate file needs to be downloaded when first encountered, so it should be kept relatively small by ensuring that most commonly needed stylesheets are added to every page.
  • 'weight': The weight of the stylesheet specifies the order in which the CSS will appear relative to other stylesheets with the same group and 'every_page' flag. The exact ordering of stylesheets is as follows:

    • First by group.
    • Then by the 'every_page' flag, with TRUE coming before FALSE.
    • Then by weight.
    • Then by the order in which the CSS was added. For example, all else being the same, a stylesheet added by a call to drupal_add_css() that happened later in the page request gets added to the page after one for which drupal_add_css() happened earlier in the page request.
  • 'media': The media type for the stylesheet, e.g., all, print, screen. Defaults to 'all'.
  • 'preprocess': If TRUE and CSS aggregation/compression is enabled, the styles will be aggregated and compressed. Defaults to TRUE.
  • 'browsers': An array containing information specifying which browsers should load the CSS item. See drupal_pre_render_conditional_comments() for details.

Return value

An array of queued cascading stylesheets.

See also

drupal_get_css()

42 calls to drupal_add_css()
ajax_forms_test_lazy_load_form_submit in modules/simpletest/tests/ajax_forms_test.module
Form submit handler: Adds JavaScript and CSS that wasn't on the original form.
bartik_preprocess_html in themes/bartik/template.php
Add body classes if certain regions have content.
bartik_preprocess_maintenance_page in themes/bartik/template.php
Implements hook_preprocess_maintenance_page().
block_admin_demo in modules/block/block.admin.inc
Menu callback for admin/structure/block/demo.
CascadingStylesheetsTestCase::testAddExternal in modules/simpletest/tests/common.test
Tests adding an external stylesheet.

... See full list

3 string references to 'drupal_add_css'
CascadingStylesheetsTestCase::setUp in modules/simpletest/tests/common.test
Sets up a Drupal site for running functional and integration tests.
CascadingStylesheetsTestCase::testReset in modules/simpletest/tests/common.test
Makes sure that reseting the CSS empties the cache.
overlay_render_region in modules/overlay/overlay.module
Renders an individual page region.

File

includes/common.inc, line 2966
Common functions that many Drupal modules will need to reference.

Code

function drupal_add_css($data = NULL, $options = NULL) {
  $css = &drupal_static(__FUNCTION__, array());

  // Construct the options, taking the defaults into consideration.
  if (isset($options)) {
    if (!is_array($options)) {
      $options = array('type' => $options);
    }
  }
  else {
    $options = array();
  }

  // Create an array of CSS files for each media type first, since each type needs to be served
  // to the browser differently.
  if (isset($data)) {
    $options += array(
      'type' => 'file',
      'group' => CSS_DEFAULT,
      'weight' => 0,
      'every_page' => FALSE,
      'media' => 'all',
      'preprocess' => TRUE,
      'data' => $data,
      'browsers' => array(),
    );
    $options['browsers'] += array(
      'IE' => TRUE,
      '!IE' => TRUE,
    );

    // Files with a query string cannot be preprocessed.
    if ($options['type'] === 'file' && $options['preprocess'] && strpos($options['data'], '?') !== FALSE) {
      $options['preprocess'] = FALSE;
    }

    // Always add a tiny value to the weight, to conserve the insertion order.
    $options['weight'] += count($css) / 1000;

    // Add the data to the CSS array depending on the type.
    switch ($options['type']) {
      case 'inline':
        // For inline stylesheets, we don't want to use the $data as the array
        // key as $data could be a very long string of CSS.
        $css[] = $options;
        break;
      default:
        // Local and external files must keep their name as the associative key
        // so the same CSS file is not be added twice.
        $css[$data] = $options;
    }
  }

  return $css;
}

Comments

An example, if you're calling drupal_add_css() from your own module (in my case, named custom.module):

<?php
drupal_add_css
(drupal_get_path('module', 'custom') . '/css/custom.css', array('group' => CSS_DEFAULT, 'every_page' => TRUE));
?>

This tells Drupal that my custom stylesheet should be grouped with other modules (CSS_DEFAULT), and should be added to every page on the site.

This is assuming your calling it from template.php

drupal_add_css(path_to_theme() . '/css/ie/ie-7.css', array('group' => CSS_THEME, 'weight' => 115, 'browsers' => array('IE' => 'lte IE 7', '!IE' => FALSE), 'preprocess' => FALSE));

When you need a separate front-page template ('page--front.tpl.php'), some times it is extremely useful to have a separate front page css file, lets say '/css/page--front.tpl.css' in your theme directory.

Include separate css file to into your 'page--front.tpl.php' template with this line:
drupal_add_css($directory.'/css/page--front.tpl.css', array('group' => CSS_THEME, 'every_page' => FALSE));

It would be great if someone would confirm this. I struggled for hours trying to figure out why a simple drupal_add_css would not work. I only got it work when I moved the css into the base directory e.g.

This did not work
drupal_add_css('a/b/c/d/e/f/g.css');

but this worked

drupal_add_css('g.css');

This is a linux environment so this was a real surprise.

@rnantogmah
drupal_add_css(base_path() . 'a/b/c/d/e/f/g.css');
or
drupal_add_css(drupal_get_patch('theme', 'yourtheme') . 'g.css');

This should read:

<?php drupal_add_css(base_path() . '/a/b/c/d/e/f/g.css'); ?>
or
<?php drupal_add_css(drupal_get_path('theme', 'yourtheme') . '/g.css'); ?>

Note the extra slashes (and path instead of patch).

use option inline.

drupal_add_css('#edit-overlay-control {display:none;}',$option['type'] = 'inline');

I've used this in a custom module within a hook_form_alter() function.

It worked beautifully until I realised it didn't work on validation error pages - for example submitting the form without required fields filled.

What i didn't realize at the time was that the data needs to be added to the FAPI array itself as it wouldn't be called upon as the form is cached.

So, if you're using drupal_add_css() or drupal_add_js() in a hook_form_alter() or hook_form_FORM_ID_alter() function you should use the form #attached function and not the drupal_add_ functions

See #attached: http://api.drupal.org/api/drupal/developer--topics--forms_api_reference....

Here is an example:

function MYMODULE_hook_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'CONTENT_TYPE_node_form') {

    $form['SOMEFIELD']['#disabled'] = TRUE; //disables field from editing

    $form['#attached']['css'] = array(
      drupal_get_path('module', 'MYMODULE') . '/includes/css/MYMODULE.css',
    );
}

Credit goes to Andy at stackexchange for pointing this out to me: http://drupal.stackexchange.com/questions/17023/custom-module-drupal-add...

In this case $bodybg is filled with a random image.

<?php
    drupal_add_css
(
     
'body {background-image: url('. base_path() .'sites/default/files/bodybg/'. $bodybg .');}',
      array(
       
'group' => CSS_THEME,
       
'type' => 'inline',
       
'media' => 'screen',
       
'preprocess' => FALSE,
       
'weight' => '9999',
      )
    );
?>

Is it possible to remove one specific css file called before ?

If you're trying to add this via the attached function in forms api, the filename has to be the key of the options array:

$form['#attached']['css'] = array(
  drupal_get_path('module', 'example') . '/example.css.' => array(
    'group' => CSS_THEME,
  ),
);

If you are adding CSS in THEME_preprocess_node you will need to add this after your drupal_add_css call.

  $variables['styles'] = drupal_get_css();

This is because $variables['styles'] gets created before preprocess_node.

Since my theme had main CSS file named css/style.css and then I wrote custom module had CSS file name as well as main theme, when I added custom module CSS called by hook_init() it never come up until I replaced the custom module CSS file to be css/module.css and it works. Spend much time as I didn't find this solutions in google.

It seems like the 'browsers' option is not working correctly. I've added this to my template file:
'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE)

but I still end up with this in my page source.
<!--[if IE]>

Am I missing something or does this just not work correctly?

I had some regex in my template.php that was ripping out the lte IE 8 part so please disregard.

in a preprocess_html for example :

  drupal_add_css('some_path' . '/css/ie_minus.css',
    array(
      'browsers' =>
      array(
        'IE' => 'lte IE 8',
        '!IE' => TRUE),
    )
  );

will add the file for IE browsers that are less than IE8 and will also add it for every browser that is not IE

  drupal_add_css('some_path' . '/css/ie_minus.css',
    array(
      'browsers' =>
      array(
        'IE' => 'lte IE 8',
        '!IE' => FALSE),
    )
  );

will only add the file for IE browsers that are less than IE 8. it will not add it to non IE browsers.

i am using drupal_add_css() in my THEME_preprocess_html(). But its not adding it to header.
Here is my code:

function MYTHEMENAME_preprocess_html(&$variables){
  $theme_path = base_path() . path_to_theme();
  drupal_add_css($theme_path.'/assets/css/style.css');

Can anyone see any issue in it? Please identify.
Thanks!

I'm having a strange issue when calling drupal_add_css from a template tpl.php file. After I clear my cache the template file loads example.css fine the first time, but if I refresh the page or navigate to other pages where the template file is also being used - example.css does NOT get loaded. Has anyone else experienced this?

My module is structured like this:
example_module
|-- example_module.info
|-- example_module.module
|-- templates
---|-- example-block.tpl.php
|-- css
---|-- example.css

Here's my module's code:

<?php
/**
* Implements hook_block_info().
*/
function example_module_block_info() {
 
$blocks['example_block'] = array (
   
'info' => t('Example Block'),
   
'cache' => DRUPAL_CACHE_PER_ROLE,
  );
  return
$blocks;
}

/**
* Implements hook_block_view().
*/
function example_module_block_view($delta = '') {
  global
$theme;
  switch(
$delta) {
    case
'example_block':
      if(
user_access('access content')) {
       
$block['subject'] = t('Example Title');
       
$block['content'] = theme(array('example_block', 'block'));
      }
      break;
  }
  return
$block;
}

/**
* Implements hook_theme().
*/
function example_module_theme() {
 
$module_path = drupal_get_path('module', 'example_module');
  return array(
   
'example_block' => array(
     
'template' => 'example-block',
     
'path' => $module_path.'/templates',
     
'pattern' => 'example-block__',
  );
}
?>

And here's the template file example-block.tpl.php, where drupal_add_css is being called:

<?php
drupal_add_css
(drupal_get_path('module', 'example_module') . '/css/example.css', array('group' => CSS_DEFAULT, 'every_page' => FALSE));
?>

<div>Some example block content</div>

Once your block is cached, either your caching is on or you have defined your block to be cached in hook_block_info() then CSS and JS files will fail to be included.

Drupal 7 manage the block as a render array and #attached property is used to manage the css and js files of respective block. Your code should be something like following code :

<?php
/**
* Implements hook_block_info().
*/
function example_module_block_info() {
 
$blocks['example_block'] = array (
   
'info' => t('Example Block'),
   
'cache' => DRUPAL_CACHE_PER_ROLE,
  );
  return
$blocks;
}
/**
* Implements hook_block_view().
*/
function example_module_block_view($delta = '') {
  global
$theme;
  switch(
$delta) {
    case
'example_block':
      if(
user_access('access content')) {
       
$block['subject'] = t('Example Title');
       
$block['content'] = array(
       
'#markup' => theme(array('example_block', 'block')),
       
'#attached' => array('css' => array(drupal_get_path('module', 'example_block').'/css/example.css')), // In similar way, you can add js, if required ('js' => array('path/example.js')).
   
);
      }
      break;
  }
  return
$block;
}
/**
* Implements hook_theme().
*/
function example_module_theme() {
 
$module_path = drupal_get_path('module', 'example_module');
  return array(
   
'example_block' => array(
     
'template' => 'example-block',
     
'path' => $module_path.'/templates',
           
'pattern' => 'example-block__',
        )
    );
}
?>

This function has been removed in Drupa 8. Adding css to the page should now be done using the #attached property of a renderable array. @see Change Record https://drupal.org/node/2169605

For some custom modules I named CSS files like css.css. Though they are at different paths, the basename that is used as identifier is css.css and overwrites all other previously added css.css files. So if you have more than one CSS file with the same name, only one file is being loaded! Use the basename option to give the file a unique name.

The parameter description at this page is sufficient enough, but I thought it was worth mentioning separately.