Question

I have a module that needs to display specific CSS values for each entry in my custom model collection.

This is trivial enough, as I can simply echo these values with PHP in my template as needed; however, I can't get over the fact that this requires me to plant an embedded style sheet in my template.

I'm essentially doing:

<?php $models = Mage::getModel('my/model')->getCollection() ?>

<style type="text/css">
    [class*='item-'] {
        display: block;
        padding: 20px;
    }
<?php foreach ($models as $model): ?>
    .item-<?php echo $model->getId() ?> {
        background: <?php echo $model->getMyColor() ?>;
    }
<?php endforeach ?>
</style>

<ul>
<?php foreach ($models as $model): ?>
    <li class="item-<?php echo $model->getId() ?>">
        <p><?php echo $model->getText() ?></p>
    </li>
<?php endforeach ?>
</ul>

The purist in me really doesn't like this approach. I start to twitch when I see the markup mixed with PHP and CSS like that... though, in all fairness, it does what it needs to do.

Is there a better approach I am missing? While I am comfortable using SASS or other CSS preprocessors, I can't rely on these being present in a random server environment.

What methods do you use to inject PHP variables into your stylesheets?

Was it helpful?

Solution

You shouldn't be trying to modify CSS with PHP, you have a other options. Without knowing that much about your module it is hard to give specific help but here are a couple of ideas:

1 - Add each colour as a class

<ul>
    <?php foreach ($models as $model): ?>
    <li class="item-<?php echo $model->getMyColour() ?>">
        <p><?php echo $model->getText() ?></p>
    </li>
    <?php endforeach ?>
</ul>

2 - Add an inline style to the element

<ul>
    <?php foreach ($models as $model): ?>
    <li class="item-<?php echo $model->getId() ?>" 
        style="background-color:#<?php echo $model->getMyColor();?>">
        <p><?php echo $model->getText() ?></p>
    </li>
    <?php endforeach ?>
</ul>

Inline styles are perfectly acceptable for one-off styles, which sounds like what you're after. This style will not be re-used anywhere else and the individual rules might be too numerous to code.

OTHER TIPS

If your style is dynamic, why not use inline styles. I know it's not clean, but it's cleaner than adding a style tag in your template. Just add in one of your css files this:

.custom-item {
    display: block;
    padding: 20px;
}

IN this class you can add all the common properties for your items and in the template just do this:

<?php foreach ($models as $model): ?>
    <?php $color = $model->getMyColor()?>
    <li class="custom-item"<?php if ($color) : ?> style="background:<?php echo $color;?>"<?php endif;?>>
        <p><?php echo $model->getText() ?></p>
    </li>
<?php endforeach ?>

I ended up adding some helper methods for various items. What was unappealing about the inline method is that, while it's fine for a random display: none; here or there, or other basic rules, it's not appropriate to plaster your markup with complex CSS in inline styles.

What I have now is:

<ul>
<?php foreach ($models as $model): ?>
    <!-- Inline styles for each item -->
    <?php $styles = $myHelper->getListInlineCSS($model->getId()) ?>
    <li class="item-<?php echo $model->getId() ?>" style="<?php echo $styles ?>">
        <p><?php echo $model->getText() ?></p>
    </li>
<?php endforeach ?>
</ul>

The helper method looks like:

public function getListInlineCSS($id)
{
    $inlineCSS = '';
    // Getting colors from each model using these methods that support returning rgba values as well as rgb values for IE < 9 support.
    $inlineCSS .= 'background: ' . $this->textBoxBg($id, true) . '; '; // returns rgb(xxx,xxx,xxx)
    $inlineCSS .= 'background: ' . $this->textBoxBg($id) . '; '; // returns rgba(xxx,xxx,xxx,xxx)
    $inlineCSS .= 'color: ' . $this->textBoxText($id, true) . '; ';
    $inlineCSS .= 'color: ' . $this->textBoxText($id) . '; ';

    return $inlineCSS;
}

This is a pretty basic form of what I was after, so I will likely expand on this to handle many different elements appropriately.

Every page has his own layout-handle. This way you can add a css file exactly to this one page, for examle:

<catalog_product_compare_index translate="label">
    <action method="addItem"><type>skin_css</type><name>css/styles-ie.css</name><params/><if>lt IE 8</if></action>
</catalog_product_compare_index>

You can leave out the <if> statement if you want.

Also, the HTML tag has this layout handle added as a class name. See `page/1column.phtml' template for an example:

...
<body<?php echo $this->getBodyClass()?' class="'.$this->getBodyClass().'"':'' ?>>
....

The resulting markup might be something like:

<body class="cms-index-index cms-home">

Using these two methods you can easily style elements on a per-page basis.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top