Advanced Stencil Docs

How to create your own custom stencils.

Example (basic) Stencil

<div class="container">
    <ad />
    <div class="headline" if="headline">{{headline}}</div>
    <div class="entries" livelist>
        <div class="entry {{(entry.image || ? 'withMedia' : 'withoutMedia'}}">
            <author-image cover />
            <author-name />
            <media src="entry"></media>
            <message autoscroll />


In the CSS, for body,

  • overflow: hidden; - this ensures that scrollbars won't show up
  • cursor: none !important; - this ensures that the mouse pointer won't show up


The element containing the "livelist" (parent) attribute should have a single child element (child.) The parent should be pluralized version of child class. (Examples: entries:entry, responses:response)

The livelist will contain all of the posts sent to air. The child element is used as a template for each of the posts.

Other options for this element:

  • max-entries="_" - specify the number of entries before ng-leave (see animation) is applied. Default is 15
  • livelist-insert="bottom" - entries are placed at the bottom of the dom. Default is top


(child of livelist)

More options:

  • post-shift - add this attribute to animate many posts so that each one moves down to allow room for the new one coming in
    • to adjust the margin between posts, use post-shift=25px. The default is 15px


<message />

will be expanded to:

<message style="display: block;">

With this tag, the recommended CSS starting point is:

message {
    width: __px;
    max-height: __px;

More options for the message tag:

  • autoscroll - scrolls the text vertically when the text is longer than the max-height set in CSS
  • autocrawl - crawls the text horizontally and in a single line, when it is longer than the width
    • For more information on autoscroll and autocrawl, see this: Autoscroll


<author-image />

will be expanded to:

    <img if='entry.author_image' class='author-image' src='{{entry.author_image}}' />

With this tag, the recommended CSS starting point is:

.author-image {
    max-width: __px;
    max-height: __px;

More options for the author-image tag:

  • adding the attribute cover will cover the area with the image, cropping when necessary.
  • adding the attribute contain will make the image fit inside the area, without cropping


<author-image cover />

will be expanded to this:

    <div if='entry.author_image' class='author-image' style='background: url({{entry.author_image}}) no-repeat 50% 30%/cover'>
        <img src="{{entry.author_image}}" height=0 width=0 />

With this tag, the recommended CSS starting point is:

.authorImage {
    width: __px;
    height: __px;


<media src="entry" />

src="entry" is required. Media will be centered (vertically or horizontally) and scaled to fit inside the constraints set in CSS.

this will be expanded to (roughly):

<media src="entry">
    <div class="vp-mediaContainer">
        <img class="vp-media" /> OR <video class="vp-media"></video>

Recommended CSS starting point:

media {
  width: __px;
  height: __px;
  display: block;

More options for the media tag:

  • no-video - shows every kind of media except video. Could also be no-image, etc.
  • video - only shows video. Could also be image, etc.
  • cover - used to crop media to cover the area.
  • collapse - used to remove padding surrounding media. Overrides width or height set in CSS.


<icon />

is expanded to:

    <i if='!entry.isFacebook' class='icon-{{entry.service}}'></i>
    <i if='entry.isFacebook' class='icon-facebook-sign'></i>

This adds the icons from FontAwesome.


<social-interaction />

is expanded to:

    <span if='entry.retweets' class='retweets'><i class='icon-retweet'></i> {{entry.retweets}}</span>
    <span if='entry.likes' class='likes'><i class='icon-thumbs-up'></i> {{entry.likes}}</span>

This will insert retweets and likes numbers, if available.

<ad />

is expanded to:

    <div class='ad' style='background: url({{ad}}) no-repeat 50% 50%/contain;'></div>

This fits an ad (if available) inside the constraints set in CSS:

.ad {
    height: __px;
    width: __px;




.ng-enter {
  transition: 500ms all ease;
  opacity: 0.0;
.vp-reset {
  opacity: 1.0;
.vp-reset {
  opacity: 0;

ng-enter is the state of the entry before it animates on.

ng-enter-active is the state of the entry after it animates on.

.ng-leave should be the same as ng-enter-active is the state of the element when it leaves.

For more information on this, see AngularJS' documentation:


Any element can have an if attribute added. This allows elements to be shown only if an argument is true.

Example, if a headline exists, this element will be shown, if there is not a headline, it will not be shown:

<div class="headline" if="headline">{{headline}}</div>



This will squeeze a single line of text to fit inside the elements constraints, as set in CSS.


<div class="authorName" squeeze-to-fit>{{entry.author_name}}</div>


    .authorName {
        width: 200px;
        height: 45px;

Conditional classes

Similar to if, this can be used to set a class if an argument is true.

Example, if an entry image exists, the class will be withImage, if not, the class will be withoutImage

<div class="{{entry.image ? 'withImage' : 'withoutImage'}}"></div>

{{ (argument) TRUE? 'this' NOTTRUE: 'thenthis' }}

This is useful for setting the message width smaller if there is an image, without floating.

  • adding ! before the argument, means it opposite (not true) (!entry.author_handle)
  • if you add || in between two arguments, then either one must be true (entry.image ||
  • if you add && in between, both must be true (entry.author_name && entry.author_handle)

Stencil Parameters

These are useful to create variables that can be controlled from Producer. There are many use cases. Here's a couple.

Hashtag - When the producer wants viewers to use different hashtags for different shows

<div class="headline">Post your comments with {{stencilParam.hashtag}}</div>

Background - Producer can select from a predefined list of backgrounds

<div class="container" style="background: url({{stencilParam.hashtag}});">

Headline - Producer can select from a list of headlines.

<div class="headline" if="stencilParam.headlines">{{stencilParam.headlines}}</div>

Change Color - Producer can change color of headline text using a color picker

<div class="headline stencilParam-headline_color">{{headline}}</div>

Show Template - Producer can select a look for the template

<div class="container {{}}">


    .container {
        background: url(default.jpg);
    .headline {
        background: blue;
    /**SHOW A**/
    .container.showA {
        background: url(a.jpg);
    .showA .headline {
        background: green;
    /**SHOW B**/
    .container.showA {
        background: url(b.jpg);
    .showA .headline {
        background: yellow;


In the stencil editor, under the "Parameters" tab, click "Add New Parameter."

  • Name - This is the name that the Producer will see. It is also used to generate the slug. (Headline Text becomes headline_text)
  • Type - This is the kind of parameter you are setting

    • Text - The parameter in the stencil is replaced by this text
    • Multiple choice - The parameter in the stencil is replaced by the value of the option selected
      • "Add new option" - click this to add options
        • First box is the value that is put in the stencil
        • Second box (Alias) is what the Producer will select
    • Color picker - Producer will be able to pick a color
      • "Associated CSS property" - this sets the property to apply the color to (background-color, color, border-color)
  • Default - this is the default value

The format for using text or multiple choice parameters is stencilParam.name_slug

For using the color picker, place stencilParam-name_slug in the class attribute (or as a string: stencilParam.name_slug)

Subscribe to our newsletter. We try to send one out once a month.

See our archives.