简体   繁体   中英

Can you use handlebars.js variables in a css document?

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 .

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

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 !

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.

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 (eg 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.

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 }};    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM