Tell me more ×
Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. It's 100% free, no registration required.

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?

share|improve this question

4 Answers

up vote 2 down vote accepted

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.

share|improve this answer
Option 1 simply cannot work. A class name of item-rgba(87,43,23,0.7) would be invalid. Option 2, inline styles feel sloppier than using embedded styles since there will likely be not just one style added, but several styles added to several different elements, leaving the embedded style as a more organized solution. – pspahn Mar 15 at 16:36
I revisited this some, and ended up using inline styles; however, instead of putting the style attribute and all the styles on the markup directly, I offloaded that to a helper method and simply call $helper->getElementInlineCSS(), keeping my templates nice and clean. – pspahn Mar 21 at 18:28
Great solution, good luck with the project – jharrison.au Mar 21 at 22:02

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 ?>
share|improve this answer
I used embedded styles instead of inline styles simply because it has a cleaner appearance and the markup isn't getting polluted with a bunch of inline styles. My example was a bit simplistic. – pspahn Mar 15 at 16:39

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.

share|improve this answer

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.

share|improve this answer
This has nothing to do with my question. – pspahn Mar 15 at 16:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.