4

I am interested in doing some conditional formatting and thought that the nicest way would be to do something like:

Inside the CSS document

{{#if something }}
    /* some css */

{{else}}
    /* some other css */

{{/if}}

But I've searched a bit and only found Django related stuff. Is this possible in handlebars or any other js library?

Note: I use Meteor.

5 Answers 5

1

Not natively in CSS, no. But take a look at SASS: http://sass-lang.com/ or LESS: http://lesscss.org, those are two CSS preprocessors that can do what you're asking

Sign up to request clarification or add additional context in comments.

Comments

1

It is possible to achieve what you want because after all, templating engines generate text, the context determines if it should be interpreted as HTML, SVG or CSS.

The technique I'm using is a bit counter-intuitive because it uses the style tag and we've been taught to stay away from embedding our CSS inside HTML pages, but the purpose of this recommendation is to separate HTML and CSS, which is still the case in the example I'm about to explain.

Suppose you have a collection of items with 4 properties relative to how you want to render them on screen.

  • text : String of content.
  • color1 and color2 : Strings representing HTML colors.
  • gradient : Boolean; if true, use a background gradient with color1 and color2 then reverse the gradient on hover; if false, use color1 as background color then color2 on hover.

Let's fill a collection using this schema.

Items=new Collection("items");
for(var i=0;i<10;i++){
    Items.insert({
        text:"Item "+i,
        color1:"#"+Random.hexString(6),
        color2:"#"+Random.hexString(6),
        gradient:Random.choice([false,true])
    });
}

Now we define a template to iterate over our collection.

<template name="itemsList">
    <ul class="items-list">
        {{#each items}}
            {{> item}}
        {{/each}}
    </ul>
</template>

Here comes the most interesting part : we use a style tag to define our inline CSS which is produced by a dedicated subtemplate.

The itemClass template gets passed the current context which is the item being iterated over.

<template name="item">
    <li class="item item-{{_id}}">
        <style scoped>
            {{> itemClass}}
        </style>
        {{text}}
    </li>
</template>

Our template generates CSS based on the properties of the current item : conditional formatting at last ! Since we're using Meteor, your formatting will be also reactive, how cool is that ?

<template name="itemClass">
  height:64px;
  .item-{{_id}}{
    {{#if gradient}}
  background:linear-gradient(to bottom, {{color1}} 5%, {{color2}} 100%);
    {{else}}
  background-color:{{color1}};
    {{/if}}
  }
  .item-{{_id}}:hover,.item-{{_id}}:focus{
    {{#if gradient}}
  background:linear-gradient(to bottom, {{color2}} 5%, {{color1}} 100%);
    {{else}}
  background-color:{{color2}};
    {{/if}}
  }
</template>

Note : I'm using the scoped attribute of the style tag, which tells the browser that formatting defined in this section is local to the parent element (the li.item in this example), which makes totally sense.

http://www.w3schools.com/tags/att_style_scoped.asp

However this is supported only in Firefox at the moment so in other browsers the style tag produces plain old global CSS and we need a fallback : that's why I decorate the class name with the _id of the item.

If all browsers supported the scoped attribute, we could remove the item-{{_id}} class and style directly the item class instead, and it would work as expected !

1 Comment

Great response! Too bad the Scope attribute is weakly supported. But your approach is very interesting. Got me thinking into some possibilities, although I would still prefer to be able to insert some {{ }} directly inside the CSS or something similar.
0

Here are a couple of ways to do this in meteor:

Use a class helper

<template name="hello">
  <p class={{excitedClass}}>hello world</p>
</template>
Template.hello.excitedClass = function () {
  return Session.equals('excited', true) && 'excited';
};

The template helper determines the class based on the value of a session variable. You can also use this for other attributes like style.

Use conditionals in the template

<template name="hello">
  {{#if excited}}
    <p class="excited">hello world</p>
  {{else}}
    <p>hello world</p>
  {{/if}}
</template>
Template.hello.excited = function () {
  return Session.get('excited');
};

The template chooses which version of the element to render based on the value of a session variable.

2 Comments

An improvement over this would be making the class property of the element of interest a variable, and defining these clases statically in the CSS. But I would like all style related logic on the CSS if possible.
I edited the examples to use classes instead of styles. It's the same idea.
0

My own answer after reading a bit would be to create CSS static classes and change the class of the HTML elements with handlebars. Here are two examples:

The first one if plain simple. The main use would be for changing the style of whole parts in general.

<template name="mainPage" class={{somePageClass}}>
    Main page content
</template>

On Meteor you would do something like

Template.mainPage.somePageClass = function(){
    //some logic
   return someClass;
};

The next case is more interesting, requires that each element of a list has the attribute class (e.g some_element.class = "classX" ).

<template name="subTemplate">
    {{#each someList}}
        <div class={{class}}>
            Element content
        </div>
    {{/each}}
</template>

With this you could induce a styling based on the specific element. For example change the color of the background depending of the type of post in a social page or whatever.

Comments

0

you can directly give as a parameter in a css style. I tried this with handelbarjs and It is working just fine.

<style>
.invoice-box {
    max-width: 800px;
    padding: 30px;
    font-size: 16px;
    line-height: 24px;
    font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
    color: #555;
    max-height: 560px;    
    zoom: {{ zoom }};    
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.