I was planning to use LESS css in my project (PHP). I am planning to use its nested @media
query feature. I find that it fails to group the multiple media queries in the output css it generates.
For example:
// LESS
.header {
@media all and (min-width: 240px) and (max-width: 319px) {
font-size: 12px;
}
@media all and (min-width: 320px) and (max-width: 479px) {
font-size: 16px;
font-weight: bold;
}
}
.body {
@media all and (min-width: 240px) and (max-width: 319px) {
font-size: 10px;
}
@media all and (min-width: 320px) and (max-width: 479px) {
font-size: 12px;
}
}
// output CSS
@media all and (min-width: 240px) and (max-width: 319px) {
.header {
font-size: 12px;
}
}
@media all and (min-width: 320px) and (max-width: 479px) {
.header {
font-size: 16px;
font-weight: bold;
}
}
@media all and (min-width: 240px) and (max-width: 319px) {
.body {
font-size: 10px;
}
}
@media all and (min-width: 320px) and (max-width: 479px) {
.body {
font-size: 12px;
}
}
My expected output is (@media queries grouped)
@media all and (min-width: 240px) and (max-width: 319px) {
.header {
font-size: 12px;
}
.body {
font-size: 10px;
}
}
@media all and (min-width: 320px) and (max-width: 479px) {
.header {
font-size: 16px;
font-weight: bold;
}
.body {
font-size: 12px;
}
}
I would like to know if it can be done in LESS (PHP) it self or is there any simple PHP based CSS parser I can use to manipulate the output CSS to group and merge the @media queries. as shown in the below flow.
LESS file
|
V
[LESSphp compiler]
|
V
CSS file
|
V
The CSS file generated
would undergo my script
written using CSS parser
|
V
CSS file
with similar @media
grouped.
In case achieving grouped @media queries in LESS (PHP) is not an option I would like to know your suggestions on CSS parser (PHP) that can be used in the above flow.
I adapt autoCompileLess function to group media query at the end of CSS without changing the less code.
@mobile: ~"only screen and (max-width: 529px)";
.test {
color:green;
@media @mobile { color:red; }
}
.test2 {
color:red;
@media @mobile { color:blue; }
}
Compile with less by default
.test {
color:green;
}
.test2 {
color:red;
}
@media only screen and (max-width: 529px) {
.test {
color:red;
}
}
@media only screen and (max-width: 529px) {
.test2 {
color:blue;
}
}
Compile less with the following function
.test {
color:green;
}
.test2 {
color:red;
}
@media only screen and (max-width: 529px) {
.test {
color:red;
}
.test2 {
color:blue;
}
}
And the function :
<?php
function autoCompileLess($inputFile, $outputFile)
{
// load cache
$cacheFile = $inputFile.".cache";
if (file_exists($cacheFile))
{
$cache = unserialize(file_get_contents($cacheFile));
if (empty($cache)) $cache = $inputFile;
}
else
{
$cache = $inputFile;
}
// compile less
$less = new lessc;
$newCache = $less->cachedCompile($cache);
// save less cache
$saveCache = $newCache;
// search media query in CSS
preg_match_all('#@media(.*?)\{(.+?}[ \n])\}#si',$newCache['compiled'],$match,PREG_SET_ORDER);//$MatchingString now hold all strings matching $pattern.
$media = array();
// group same media query
foreach ($match as $val)
{
if (!isset($media[$val[1]])) $media[$val[1]] = '';
$media[$val[1]] .= $val[2];
}
// delete media query of cache
$newCache['compiled'] = preg_replace('#@media(.*?)\{(.+?}[ \n])\}#si', '', $newCache['compiled']);
// add groups of media query at the end of CSS
$final = $newCache['compiled'] . "\n";
foreach ($media as $id => $val)
{
$final .= "\n" . '@media' . $id . '{' . $val . '}' . "\n";
}
// save less
// save CSS with groups of media query
if (!is_array($cache) || $newCache["updated"] > $cache["updated"])
{
file_put_contents($cacheFile, serialize($saveCache));
// file_put_contents($outputFile, $newCache['compiled']);
file_put_contents($outputFile, $final);
}
}
// use of function
autoCompileLess('style.less', 'style.css');
Why don't you have your selectors in your media queries too, like your expected output? Then you would get rid of having double media queries for everything you do...