8.3.x theme.api.php hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets)
8.0.x theme.api.php hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets)
8.1.x theme.api.php hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets)
8.2.x theme.api.php hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets)
8.4.x theme.api.php hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets)
7.x system.api.php hook_css_alter(&$css)

Alter CSS files before they are output on the page.


$css: An array of all CSS items (files and inline CSS) being requested on the page.

See also



Related topics

2 functions implement hook_css_alter()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

locale_css_alter in modules/locale/locale.module
Implements hook_css_alter().
seven_css_alter in themes/seven/template.php
Implements hook_css_alter().
1 invocation of hook_css_alter()
drupal_get_css in includes/common.inc
Returns a themed representation of all stylesheets to attach to the page.


modules/system/system.api.php, line 865
Hooks provided by Drupal core and the System module.


function hook_css_alter(&$css) {
  // Remove defaults.css file.
  unset($css[drupal_get_path('module', 'system') . '/defaults.css']);


davidneedham’s picture

I just wanted to point out this implementation of hook_css_alter as used by the Ninesixty theme. It takes all of the 'framework' css files and inserts them before other css files.

That code is very easily repurposed to make reset.css (or any css files you want) to show up before other css files. Just change 'foo' to your theme name:

function foo_css_alter(&$css) {
  global $theme_info, $base_theme_info;

  // Dig into the framework .info data.
  $framework = !empty($base_theme_info) ? $base_theme_info[0]->info : $theme_info->info;

  // Pull important styles from the themes .info file and place them above all stylesheets.
  if (isset($framework['stylesheets'])) {
    foreach ($framework['stylesheets'] as $media => $styles_from_foo) {
      foreach ($styles_from_foo as $style_from_foo) {
        // Force reset.css to come first.
        if (strpos($style_from_foo, 'css/reset.css') !== FALSE) {
          $css[$style_from_foo]['group'] = $on_top;
          // Handle styles that may be overridden from sub-themes.
          foreach (array_keys($css) as $style_from_var) {
            if ($style_from_foo != $style_from_var && basename($style_from_foo) == basename($style_from_var)) {
              $css[$style_from_var]['group'] = $on_top;
hansrossel’s picture

the group CSS_SYSTEM and the weight of -1 makes sure that the reset.css comes first before all the core css and module css files

drupal_add_css(path_to_theme() . '/css/reset.css', array('group' => CSS_SYSTEM - 1, 'preprocess' => FALSE));
nicl’s picture

The Tao theme does this very simply using this hook and the code below (the code is for Drupal 7):

function tao_css_alter(&$css) {
  $exclude = array(
    'misc/vertical-tabs.css' => FALSE,
    'modules/aggregator/aggregator.css' => FALSE,
    'modules/block/block.css' => FALSE,
    'modules/book/book.css' => FALSE,
    'modules/comment/comment.css' => FALSE,
    'modules/dblog/dblog.css' => FALSE,
    'modules/file/file.css' => FALSE,
    'modules/filter/filter.css' => FALSE,
    'modules/forum/forum.css' => FALSE,
    'modules/help/help.css' => FALSE,
    'modules/menu/menu.css' => FALSE,
    'modules/node/node.css' => FALSE,
    'modules/openid/openid.css' => FALSE,
    'modules/poll/poll.css' => FALSE,
    'modules/profile/profile.css' => FALSE,
    'modules/search/search.css' => FALSE,
    'modules/statistics/statistics.css' => FALSE,
    'modules/syslog/syslog.css' => FALSE,
    'modules/system/admin.css' => FALSE,
    'modules/system/maintenance.css' => FALSE,
    'modules/system/system.css' => FALSE,
    'modules/system/system.admin.css' => FALSE,
    'modules/system/system.base.css' => FALSE,
    'modules/system/system.maintenance.css' => FALSE,
    'modules/system/system.menus.css' => FALSE,
    'modules/system/system.messages.css' => FALSE,
    'modules/system/system.theme.css' => FALSE,
    'modules/taxonomy/taxonomy.css' => FALSE,
    'modules/tracker/tracker.css' => FALSE,
    'modules/update/update.css' => FALSE,
    'modules/user/user.css' => FALSE,
  $css = array_diff_key($css, $exclude);

Note, the Omega theme (in its Alpha base theme) also has an interesting way to remove core CSS files. It does this by specifying excluded CSS files in the .info file and then using some functions -alpha_settings() and then (same as Tao) hook_css_alter() - to unset the specified css.

The Tao approach is much much simpler in terms of code. But Omega is nice too because it is very friendly to non-developers (just add exclude[] to your info to remove a CSS file).

gausarts’s picture

You can now use theme.info to remove CSS like in D6, see http://drupal.org/node/901062

akagroundhog’s picture

You may remove different groups of CSS (CSS_SYSTEM, CSS_DEFAULT, CSS_THEME) by adding something like this to your template.php (the following example will remove everything but theme-layer CSS):

function foo_css_alter(&$css) {
  foreach ($css as $key => $value) {
    if ($value['group'] != CSS_THEME) {
      $exclude[$key] = FALSE;
  $css = array_diff_key($css, $exclude);
FAAREIA’s picture

Many thanks for that code, i was looking for that function. Didn't know there were groups.


tassaf’s picture

System.theme.css causing a problem for me
table {
border-collapse: collapse;

Here is the problem
If I disable system.theme.css what will happen? is this file important or I can disable it without any effect?

pachabhaiya’s picture

Module-layer and System-layer css should still exist for logged-in users.
Here's the solution:

function cp_css_alter(&$css) { 
	/* Only use theme-layer css for logged-out users,
	 * remove module-layer and system-layer css
	 * ================================================
	 * $value['group'] = 100 = CSS_THEME = (Theme-Layer CSS)
	 * $value['group'] = 0 = CSS_DEFAULT = (Module-Layer CSS)
	 * $value['group'] = -100 = CSS_SYSTEM = (System-Layer CSS) */
	foreach ($css as $key => $value) {
		if ($value['group'] != CSS_THEME) {
			$exclude[$key] = FALSE;
	if (!(bool)$GLOBALS['user']->uid){
		$css = array_diff_key($css, $exclude);
Coyote6GraphX’s picture

To remove specific CSS files from a specific page in Drupal 7, use both hook_preprocess_page (&$variables) & hook_css_alter (&$css);

// In preprocess page function
// add a custom style sheet for the page.
function hook_preprocess_page (&$variables) {

	// Find the exact page to change.
	if (isset ($variables['node']->nid) && $variables['node']->nid == 2148) {
		// Add the new css.
		drupal_add_css (path_to_theme() . '/css/custom.css', array('type' => 'file'));



// In the css alter function
// check for your custom css
// and remove the desired css files
// if it was found.
function hook_css_alter (&$css) {

	// Remove the undesired style sheets
	// if the custom one is found.
	if (isset ($css[path_to_theme() . '/css/custom.css'])) {
		unset ($css[path_to_theme() . '/css/design.css']);
		unset ($css[path_to_theme() . '/css/print.css']);


I hope Drupal 8 makes a drupal_remove_css function, but in the mean time I hope this helps some people out.

favosys’s picture

This is exactly what I needed, worked perfect the first time, clear easy to read and understand code instead of vague stuff that people have to figure out.

Again thanks, this may be one of the best comments ever

daxiuge’s picture

* Implements hook_css_alter().
function biz_css_alter(&$css) {

//unset css file
unset($css[drupal_get_path('module', 'system') . '/system.base.css']);

//add css code inline
$css[] = array(
'type' => 'inline',
'group' => -100,
'weight' => 0.001,
'every_page' => true,
'preprocess' => true,
'media' => 'all',
'browsers' => array('IE' => true, '!IE' => true),
'data' => '.element-invisible {display:none;}',