Question

i'm working on a script that generates multiple CSS into one. And Here is the script.

    $full_string = "";

    foreach($allfiles as $curfile => $file) {           
        $file = $PATH[$curfile] . $file;
        $file_open = fopen($file , 'r');
        $concat = "\n" . fread($file_open , filesize($file)) . "\n";
        $full_string .= $concat;
        fclose($file_open);
    }

    return $full_string;

Here i'm combining all the CSS files into one. But the problem now is i have to compare the current CSS($file) with another css(let's consider it as overrider.css). And if $file is having a style like,

h1 {
    color: white; 
    background: teal; 
    FONT-FAMILY: arial, helvetica, lucida-sans, sans-serif; 
    FONT-SIZE: 18pt; 
    FONT-STYLE: normal; 
    FONT-VARIANT: normal;
}

body 
{
    font-family: arial;
    FONT-SIZE: 14px; 
}

and if overrider.css is having a style like,

body 
{
    font-family: Calibri;
    color: #3E83F1; 
}

Then final CSS(output.css) generated should be,

h1 {
    color: white; 
    background: teal; 
    FONT-FAMILY: arial, helvetica, lucida-sans, sans-serif; 
    FONT-SIZE: 18pt; 
    FONT-STYLE: normal; 
    FONT-VARIANT: normal;
}

body 
{
    font-family: Calibri;
    FONT-SIZE: 14px;
    color: #3E83F1;
}

Here, since style for body in override.css have font-family, it replaces the font-family property in original CSS and since the color is a new property which is not present in ($file) which is original CSS file, so it should add the property to original CSS file. So how to achieve this in PHP, since i don't have any idea on parsing CSS. Any idea on this would be greatly appreciated.

Please note that i need to generate a new CSS file by giving the input as file1($file) and file2(override.css) and we need to genrate output.css with the styles overridden.

Thanks in advance.

Was it helpful?

Solution

There are a few CSS parsers available (google "php css parser"), like this one that I didn't try, but seems interesting. But personally I'd do the parsing myself - following that kind of pseudo-PHP algorithm

  • read all the files into one string Str, with all "\n", "\r" and "\t" replaced by a space (to make parsing (a bit) easier)

then, function to process (selector => rules)

func deal with selectors and rules:

rules = array()
do {
  S = string from current pos to next `{` excluded (selectors)
  R = string from '{' to next '}' (rules)
  r = explode(';', R) 
  lr = make array of rules from r trimmed elements
  s = explode (',', S)
  ls = make array of [selector => lr]

  // same sel: latest rule overwrite existing, added if not exist
  merge ls into rules 
} while (not '}' and not '@' and not EOF); // the '}' would be the closing media

return rules

Main function to deal with medias, and then call the above function

medias = array();

func deal with Str
do {
  if (first non blank char is @) {
     media = array of listed medias
     eat fist '{'
  }
  else {
     media = array ('GLOBAL')
  }
  selectorsrules = deal with selectors and rules(rest of Str)

  foreach (media as m) {
    merge in medias(m) selectorsrules, same procedure as above
  }
} while (not EOF);

Interesting project but I don't have the time to implement it fully. Result is in medias array.

OTHER TIPS

if you want font-family: arial; to be apply then add it as font-family: arial !important;

you do not need to worry about merging them because browser will automatically add color to body tag from second css of color found in first css then it will overwrite it with second css.

You have 2 choices:

  1. The simple way is to change your css files and add !important where it is important to be there. It is correct to have for example "body" in css more than 1 time. And whenever you a style to be overridden leave it. Ofcourse this kind of approach is mostly manual. You have to know where it will be overwritten and where not.

  2. The second approach requires string parsing, regular expressions, and i mean you should know your way around the string ad how to parse them. You should get each of the files content, save them to a string, and you should compare them using regex to if a tag is exists in both, then merge the tags content. This way is easy to say but hard to implement.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top