Search code examples
phpregexstylesmedia-queries

Regular expression for media queries in CSS


I'm searching for a way to extract media queries from a CSS file.

/* "normal" css selectors

@media only screen and (max-device-width: 480px) {
    body{-webkit-text-size-adjust:auto;-ms-text-size-adjust:auto;}
    img {max-width: 100% !important; 
         height: auto !important; 
    }
}

@media only screen and (max-device-width: 320px) {
    .content{ 
        width: 320px;
    }
}

now I like to get only the media queries. I though the begin is always @media and the end of the search is always a curly bracket followed by some optional whitespace and another curly bracket.

The only thing I have is

preg_match_all('#@media ?[^{]+?{XXX#',$stylesheetstring, $result);

were XXX is the missing part I'm searching for.

The current one (without the X) only returns the first line (obviously)


Solution

  • Assuming you want the entire media block, I don't think this is the right job for regex.

    You could however, implement a simple parsing function:

    function parseMediaBlocks($css)
    {
        $mediaBlocks = array();
    
        $start = 0;
        while (($start = strpos($css, "@media", $start)) !== false)
        {
            // stack to manage brackets
            $s = array();
    
            // get the first opening bracket
            $i = strpos($css, "{", $start);
    
            // if $i is false, then there is probably a css syntax error
            if ($i !== false)
            {
                // push bracket onto stack
                array_push($s, $css[$i]);
    
                // move past first bracket
                $i++;
    
                while (!empty($s))
                {
                    // if the character is an opening bracket, push it onto the stack, otherwise pop the stack
                    if ($css[$i] == "{")
                    {
                        array_push($s, "{");
                    }
                    elseif ($css[$i] == "}")
                    {
                        array_pop($s);
                    }
    
                    $i++;
                }
    
                // cut the media block out of the css and store
                $mediaBlocks[] = substr($css, $start, ($i + 1) - $start);
    
                // set the new $start to the end of the block
                $start = $i;
            }
        }
    
        return $mediaBlocks;
    }