I am using CartoCSS to style features in a run-time CartoDB layer (as opposed to a pre-made visualization) but it gets messy doing this within JavaScript:

sublayers: [{
  cartocss: '#initvisitedfws {bottom/marker-width: 24; bottom/marker-ignore-placement:false; bottom/marker-fill: gold; bottom/marker-allow-overlap:true; top/marker-width: 14; top/marker-fill: #111; top/marker-file: url(clock.svg); top/marker-allow-overlap:true;',
  interactivity: 'cartodb_id, parent',
  sql: "SELECT * FROM subprojects"

I could keep it somewhat neat by using multi-line strings but that becomes unsightly and tedious in its own way, so I would prefer to edit the CartoCSS in its own native .mss file (especially in tandem with this Sublime Text 2 .mss syntax/autocomplete package).

The ghetto-ish way I am approaching this is with an XMLHttpRequest:

function getMss() {

  var xmlhttp;
  xmlhttp=new XMLHttpRequest();
  xmlhttp.open('GET', "somepath/somefile.mss", false);

  var mapStyle = xmlhttp.responseText;
  return mapStyle;


...and then calling it from the CartoDB sublayer parameters:

var cartodbParams = {
  user_name: 'user_name',
  type: 'cartodb',
  interaction: true,
  sublayers: [{
    cartocss: getMss(),
    interactivity: 'cartodb_id, parent',
    sql: "SELECT * FROM subprojects"

This works fine but leads to another HTTP request, and I'm also not optimistic about its maintainability once I have dozens or hundreds of rules and multiple map layers.

So, what is a better solution for using CartoCSS within JavaScript?


We use a trick like:

<style type="cartocss/text" id="simple">
        marker-fill: #FF6600;
        marker-allow-overlap: true;

and after that

cartocss: $("#simple").text();
  • Wow, I would not have thought of that. It's certainly cleaner than JS, so I will try it and mark as correct if it works, but I was hoping to keep the MSS file preserved. I'm sure I could automate something to inline it as you showed, but I'd prefer to point to it within the style tag, like <style type="cartocss/text" id="simple" src="simple.mss">. Is that possible? – abettermap Dec 24 '14 at 2:27
  • @abettermap no idea, better to take a look at, for instance, less.js which does that: github.com/less/less.js/blob/master/lib/less-browser/… looks like they load those files using XHR – javisantana Dec 25 '14 at 11:04

I accepted @javisantana's answer but would like to provide some of my own findings and didn't want to muck up my original question, so here you go:


The accepted answer works great and is likely the most semantic approach, but I found myself using plain old <span> elements (or <div> or whatever) to house the mss since I was often in WordPress land, did not have access to the <head>, and did not want to include a <style> tag in the <body> (even though it's probably cool, who knows).

To make sure it wasn't visible, I just added a CSS class: .never-show {display: none;}

...to the tag: <span class="never-show">...</span>


I really, really like being able to edit .mss files in a text editor with CartoCSS syntax highlighting, so the Sublime Text package I mentioned before is not something I wanted to leave, nor did I want to use it and then paste the mss into the HTML.

SO, I went the PHP route instead:

    <span id="mss_my-sublayer" class="never-show">
          $contents = file_get_contents( 'path/to/my-sublayer.mss');
          echo $contents;

Accessing and Modifying

I had multiple sublayers in the map, so I wanted a reusable function to grab the mss for each, and to modify it when I had a "selected" feature:

    function getMss(sublayerName, cartodb_id){

        // Get contents of HTML element containing this sublayer's mss, as
        // suggested by javisantana:
        var mss = $('#mss_' + sublayerName).text();

        // New MSS:
        var newMss = '';

        // If cartodb_id is passed in, append the "selected" style:
        if (cartodb_id){

            // Note that I needed the zoom stuff here in order to increase
            // specificity. This had no impact on the style if I didn't!
            newMss = '#' + sublayerName + '[cartodb_id=' + cartodb_id + ']' + 
                '[zoom>1][zoom<22]' +
                '{marker-fill: red;}';


        // newMss is empty if no cartodb_id, which effectively resets
        // any sublayers to their default style by only using original mss. 
        // Otherwise, selected point feature is red:
        return mss + newMss;



Not going to get into how to access sublayers, or the data of a clicked feature, so this assumes you're in the know. :) For a sublayer WITHOUT a selected feature, just don't pass in a cdbId to this function. To set the style for a sublayer whose feature was SELECTED:

    // var cdbId = cartodb_id of the selected feature
    // var mySublayer = the sublayer whose CSS is being reset:

    mySublayer.setCartoCSS(getMss('my-sublayer', cdbId));

Here it is in action: http://friendsofsleepingbear.org/sbht-i-map

I'm sure there is much room to expand on this (API, anyone?), but I hope it helps. Thanks again to javisantana for getting this ball rolling, and it seems to be the preferred method of CartoDB as well.

Your Answer

