我有一个我要合并的css数组

时间:2011-04-13 23:05:07

标签: php css optimization

我有一个用于创建模板的HTML类。 我的班级是这样的:

<?php
$page = \TEST\HTML::dispense(':html');
$page->mainWrapper(':div') //creates a child object by using __call() and sets the "div" model
->id('mainWrapper') //sets id
->style('background','red') //adds a style
->text('blah') //adds a text
->addClass('someClass'); //adds a class
->someSpan(':span')
->addClass('spanClass')->addClass('someClass')
->style('font-size','12pt')
->style('border-bottom','1pt dashed black')
->style('background','red');
?>

这使我能够快速开发html标记,而不必担心丢失的字符或错误引用的属性。一切都被缓存,我没有性能问题。

现在我想更进一步。在生产模式下,一切正常,但对于最终输出,我想删除所有内联“样式”属性并最小化它们并将它们缓存在css文件中。 现在,我有一个循环遍历所有HTML对象的函数,并根据标记,id和类聚合数据。 我的问题是:一旦我以这种形式获得了整齐的css数组:

$style['tag']['.class']['#id']['styleKey'] = styleValue

如何修剪冗余值,以便留下相关的css文件?缩小和gzipping可以在稍后阶段进行。我现在想要的是比较值并在转储之前优化数组,以便将具有相同标记/ id /类的所有元素共同的所有'styleKeys'组合在一起。

所以在上面的例子中,例如,由于两个元素(div和span)共享样式“background:red”和类“someClass”,我将有一个“someClass”CSS规则“background:红色的“

如果有任何兴趣,这是我的“提取方式”功能:

<?php
public static function extractStyles($element, array &$styles=array()){
    if($element instanceof \TEST\HTML){$element = $element->htmlData();}
    $tag = isset($element['#acronym']) ? $element['#acronym'] : NULL;
    $id = isset($element['#id']) ? '#'.$element['#id'] : NULL;
    $classes = isset($element['#class']) ? $element['#class'] : NULL;
    if(isset($element['#style']) && ($tag || $id || $class)){
        $ref = &$styles;
        if($id){if(!isset($ref[$id])){$ref[$id] = array();};$ref = &$ref[$id];}
        if($classes){
            if(\is_array($classes)){$classes = '.'.implode('.',$classes);}
            if(!isset($ref[$classes])){$ref[$classes] = array();};$ref = &$ref[$classes];
        }
        if($tag){if(!isset($ref[$tag])){$ref[$tag] = array();};$ref = &$ref[$tag];}
        foreach($element[self::ATTRIBUTES]['#style'] as $style=>$value){
            $ref[$style] = $value;
        }
    }
    if(isset($element[self::CHILDREN]) && count($element[self::CHILDREN])){
        foreach($element[self::CHILDREN] as $child){
            self::extractStyles($child, $styles);
        }
    }
    return $styles;
}
?>

任何指针都会受到欢迎......我真的迷路了。我甚至不知道我所寻找的是否可行。

如上所述,性能暂时不是问题。如果它有效,我会找到一种优化它的方法。 此外,请不要链接到xCSS和其他框架,因为它们处理字符串,我的CSS创建为数组。 提前感谢你们给我的任何帮助!

1 个答案:

答案 0 :(得分:2)

第一顺序优化是构建层次结构树。此树中的父对子关系是子对象是父对象的超集。此树的根节点是空样式(您不会显示它)。

因此,如果你有

.parent {
    background: red;
}

.childA {
    background: red;
    border: 1px solid black;
}

.childB {
    background: red;
    font-weight: 800;
}

父级被设置为树中的最小公分母。然后可以将其压缩为3个类,文本更少。子元素将包含路径中的所有类。如果您最初拥有<span class="childA">,那么您将获得<span class="parent childA">

压缩类看起来像:

.parent {
    background: red;
}

.childA {
    border: 1px solid black;
}

.childB {
    font-weight: 800;
}

关于ID的说明,ID始终是最合适的类的子级。因此,如果你有

#menu {
    background: red;
    border: 1px solid black;
    margin: 15px 40px;
    color: white;
}

它将成为ChildA的孩子,其css将缩减为

#menu {
    margin: 15px 40px;
    color: white;
}

显示为<ul id="menu" class="parent childA">

要创建树,您将需要一个对象来存储相同子对象的数组(递归)和一个函数,当给定两个对象时,可以确定它们的css是否是子集,相等或超集,差异,或者没有共性。

如果你不熟悉二元搜索树,那么现在是讨论这个问题的好时机,尽管这会比这更复杂,但它将是朝着正确方向迈出的良好开端。


二阶优化是确定子元素的嵌套是否可以进一步减少类的需要。例如,如果<li>内的所有<ul id="#menu">内容都设置得相似,那么您可以为#menu li

创建规则

为此,您需要转到每个节点并分析其子节点。如果同一节点类型的所有子节点共享一个公共样式元素(使用上面的set comparer),则将公共集元素提取为父节点。差异成了孩子们。

让我们说你有这个例子(注意事项已经通过第1遍):

<ul id="menu" class="parent childA">
    <li class="top menuli">Item</li>
    <li class="menuli">Item</li>
    <li class="menuli">Item</li>
    <li class="menuli">Item</li>
    <li class="bottom menuli">Item</li>
</ul>

我们注意到所有<li>都有一个共同的元素.menuli,这意味着我们可以删除在第1遍中创建的这个类,并用平坦的#menu li规则替换它。我们通过从每个子li中删除menuli类,并用.menuli规则替换#menu li规则来实现此目的。

我们的css改变如下:

#menu {
    margin: 15px 40px;
    color: white;
}

.menuli {
    font-size: 30px;
    font-weight: 800;
    margin: 8px 0;
}

#menu {
    margin: 15px 40px;
    color: white;
}

#menu li {
    font-size: 30px;
    font-weight: 800;
    margin: 8px 0;
}

html失去了课程menuli

<ul id="menu" class="parent childA">
    <li class="top">Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li class="bottom">Item</li>
</ul>

在搜索节点树而不是深度优先搜索时,请记住使用广度优先搜索。如果你是积极的,你可以在许多路径上继续检查类似标签的第二级别,常见的二级搜索可能会显示#menu li a#container div p等类似的类。如果你允许,这将成为NP难题无限深度搜索。

希望这会有所帮助。如果这是你想要的方向,我很乐意帮助提供更多关于集合比较器和树搜索器的代码,尽管这样做要复杂得多。