How to maintain very tight control over the order of CSS files in the Yii Framework

There are many ways in Yii to get CSS on your pages.

The problem is that after you start using extensions, widgets, themes, etc., they all have their own stylesheets (fairly fair) and the order in which CSS is processed and inserted into the HTML depends on whether they were set in the controller, viewing or arranging or using the Yii asset manager or the Yii package manager.

Recently, our Yii project has been modified to use packages registered in config/main.php as follows:

 'clientScript'=>array( 'packages'=> array( 'theme'=>array( 'basePath'=>'yii.themes.default', 'css'=>array('css/reset.css','css/main.css','css/form.css'), 'js'=>array('js/lib.js'), 'depends'=>array('jquery'), ), ... 

This caused the CSS file to crash because it was designed to override grid styles and was now included in the CGridView stylesheet.

The solution was to add these lines at the bottom of layouts/main.php :

 $path = Yii::getPathOfAlias('yii.themes.default').'/css/style.css'; $cssFile = Yii::app()->getAssetManager()->publish($path); Yii::app()->getClientScript()->registerCssFile($cssFile); 

For me this seems like a less perfect solution, and I expect that we may have problems in the future when we forget what we have done, or we need to do something similar with another topic or another project completely.

Is there a better way to effectively manage CSS when it can be provided from many different sources?

Edit:

I am considering expanding CClientScript to provide an โ€œoverrideโ€ option in which you can specify an array of CSS files to be included after registering the file. It looks like it might be a little flaky, though ...

+6
source share
2 answers

I came up with the following solution using an approach similar to how z-index works. This is not ideal, although in any area.

The style sheets have a default priority value of 0, and you can set this with registerCss and registerCssFile to a positive or negative integer. A negative integer will insert the file before the rest of the CSS, and a positive integer will send it to the end.

In config/main.php set a new class for clientScript:

  'clientScript'=>array( 'class' => 'components\ClientScript', ... 

components/ClientScript.php :

I played with the idea of โ€‹โ€‹determining dependencies between registered files instead of priority based on integers, but did not execute it. I have left this code here for now if someone wants to accept it.

 class ClientScript extends CClientScript { protected $dependencies = array(); protected $priority = array(); public function renderHead(&$output) { $cssFilesOrdered = array(); $currentCssFiles = $this->cssFiles; if (!empty($this->priority)){ # assign 0 to anything without a specific priority # can't do this in the register method because not every CSS file that ends up here used it $cssFilesWithPrioritySet = array_keys($this->priority); foreach ($currentCssFiles as $path => $v){ if (!in_array($path, $cssFilesWithPrioritySet)){ $this->priority[$path] = 0; } } asort($this->priority); foreach ($this->priority as $path => $id){ $cssFilesOrdered[$path] = $currentCssFiles[$path]; unset($currentCssFiles[$path]); } # add any remaining CSS files that didn't have an order specified $cssFilesOrdered += $currentCssFiles; } if (!empty($cssFilesOrdered)){ $this->cssFiles = $cssFilesOrdered; } parent::renderHead($output); } public function registerCssFile($url, $media = '', $order = null) { $this->setOrder($url, $order); return parent::registerCssFile($url, $media); } public function registerCss($id, $css, $media = '', $order = null) { $this->setOrder($id, $order); return parent::registerCss($id, $css, $media); } private function setOrder($identifier, $order) { if (!is_null($order)){ if (is_array($order)){ $this->dependencies[$identifier] = $order; } elseif (is_numeric($order)){ $this->priority[$identifier] = $order; } } } } 
+5
source

I think the best way to improve the @bcmcfc function is to stay ordered by default, while guaranteeing priority work.

Here I modify the renderHead () function.

 public function renderHead(&$output) { $cssFilesOrdered = array(); $currentCssFiles = $this->cssFiles; //print_r($currentCssFiles); if (!empty($this->priority)) { // sort priority array according to value (priority number) asort($this->priority); $tmp = array_values($this->priority); $startPriority = $tmp[0]; # assign 0 to anything without a specific priority # can't do this in the register method because not every CSS file that ends up here used it $cssFilesWithPrioritySet = array_keys($this->priority); $startCounter = $startPriority-count($currentCssFiles); foreach ($currentCssFiles as $path => $v) { if (!in_array($path, $cssFilesWithPrioritySet)) { $this->priority[$path] = $startCounter++; } } asort($this->priority); foreach ($this->priority as $path => $id) { $cssFilesOrdered[$path] = $currentCssFiles[$path]; unset($currentCssFiles[$path]); } } if (!empty($cssFilesOrdered)){ $this->cssFiles = $cssFilesOrdered; } # add any remaining CSS files that didn't have an order specified $cssFilesOrdered += $currentCssFiles; parent::renderHead($output); } 
0
source

Source: https://habr.com/ru/post/921375/


All Articles