Skip to main content

Styling Exhibits with Neatline-Flavored CSS

At a glance

  • Neatline 2.0 makes it possible to use a dialect of CSS to perform bulk updates on large groups of records.
  • Neatline-inflected CSS uses a custom set of rules that correspond to the properties on the record data model.
  • Groups of records are selected using the CSS class syntax, with record tags providing the class names.

Screenshot of Stylesheets

Quick reference (for the impatient)

Neatline 2.0 makes it possible to use a simplified, Neatline-inflected dialect of CSS - integrated directly into the editing environment - to perform bulk updates on large groups of related records clustered together by tags (see the “Editing Record Groups” guide for more information about tags).

All exhibits have a built-in stylesheet:

  1. Open the editing environment for an exhibit.
  2. Click on the Styles tab. Right under the tab, you’ll see a code editor labelled “Stylesheet.”

Neatline CSS is syntactically identical to regular CSS, but semantically a bit different:

  • Instead of using DOM selectors, Neatline CSS just treats tags on records as “classes.” So, if you have a group of records that are tagged with democrat, you can select them as if “democrat” were a class on an HTML element:
  .democrat {
      fill-color: #08c;
      stroke-width: 5;
  }
  
  • To match all records in the exhibit, use the special .all tag:
  .all {
      fill-color: #08c;
      stroke-width: 5;
  }
  
  • You can’t match multiple tags with the same selector (we’re hoping to add this soon). For now, this won’t work:
  .democrat, .republican {
      fill-color: #08c;
      stroke-width: 5;
  }
  
  • Instead of using regular CSS rules, use a special set of rules that map onto properties in the Neatline data model (and, by extension, to the fields in the “Style” tab in the record edit form):

    • widgets
    • presenter
    • fill-color
    • fill-color-select
    • stroke-color
    • stroke-color-select
    • fill-opacity
    • fill-opacity-select
    • stroke-opacity
    • stroke-opacity-select
    • stroke-width
    • point-radius
    • zindex
    • weight
    • start-date
    • end-date
    • after-date
    • before-date
    • point-image
    • wms-address
    • wms-layers
    • min-zoom
    • max-zoom
    • map-focus
    • map-zoom

Rationale: Why use stylesheets?

Neatline 2.0 makes it possible to work with really large collections of records - as many as about 1,000,000 in a single exhibit. That level of scalability is liberating, but it also introduces some interesting new content management challenges. If the map can display that many records, there also need to be new tools that make it possible to effectively update and maintain content at that scale.

For example, imagine you’re plotting returns from the last four presidential elections. You import a big collection of about 800,000 records, 200,000 for each of the four elections. Each record represents an individual precinct somewhere in the country with a dot on the map, scaled according to how many votes were cast at the location and shared red or blue depending on which party won more votes. Once the data is loaded into Neatline, you realize that you want to change the shade of blue used to represent the democratic precincts. How do you do that, short of manually making the change on all ~400,000 democratic records?

This is obviously a problem with really massive data sets, but, as you work with Neatline, you’ll find that this type of problem rears its head surprisingly quickly, even with quite small exhibits in the 50- to 100-record range. The essence of the problem is this - records are almost never “unique snowflakes” in the exhibit. They almost always exist as part of some kind of general taxonomy or grouping in the exhibit - democratic, 2012, northeast, etc. And, in almost every case, those groupings should share some common attributes. All democratic records should be the same shade of blue; all precincts from 2004 should be visible on the map during the same range of dates; all precinct records should have the same basic opacity settings; ad infinitum.

But, as you can see, they shouldn’t share all of their attributes - all 2004 precincts should share the same range of dates (the “After Date” and “Before Date” fields), but they most definitely should not share the “Fill Color” field, since that would clobber out the all-important distinction between the blue democratic records and the red republican precincts. In other words, different groups of records need to share different sets of attributes.

We can map this out schematically. Here’s a list of all the “categories” in the exhibit, and the fields that should be shared for each of the categories:

  • All Precincts: Fill Opacity, Stroke Width
  • Democratic: Fill Color
  • Republican: Fill Color
  • 2000: After Date, Before Date
  • 2004: After Date, Before Date
  • 2008: After Date, Before Date
  • 2012: After Date, Before Date

How do we keep the groups synchronized? Really, this is a familiar problem - it’s almost exactly the same task as styling web pages with CSS (Cascading Style Sheets), a simple styling language that makes it possible to “select” specific parts of a page and apply a set of rules to those elements. In Neatline 2.0, it’s possible to use a simplified dialect of CSS - integrated directly into the editing environment - to model these kinds of relationships among records and keep them in sync.

In Neatline, the stylesheet system is closely tied to the tagging system. Tags are just comma-delimited lists of identifiers that can be added to each individual record under the “Style” tab in the record edit form. In this example, individual records in the collection might have tag strings that look like this:

  • precinct, democrat, 2000
  • precinct, republican, 2000
  • precinct, democrat, 2012
  • state, republican, 2008

Getting started with stylesheets

Let’s start by defining some basic, generic styles for the each of the precincts, which are all represented as dots on the map:

.precinct {
  fill-opacity: 0.5;
  stroke-width: 0;
}

Now, when I click “Save” at the bottom of the form, Neatline will update the “Fill Opacity” and “Stroke Width” of all 800,000 records tagged as precincts with 0.5 and 0. Next, let’s add the date visibility settings for each of the three election-season tags:

.2000 {
  after-date: 2000;
  before-date: 2004;
}

.2004 {
  after-date: 2004;
  before-date: 2008;
}

.2008 {
  after-date: 2008;
  before-date: 2012;
}

.2012 {
  after-date: 2012;
  before-date: 2016;
}

Likewise, when I click “Save,” Neatline will update the “After Date” and “Before Date” fields on each record depending on which election-season is assigned to it.

Auto-updating stylesheet values

This is all fine and well, but what if we don’t actually know what value we want to use? In each of these cases, we’re working with fields that have fairly “semantic” values that we can reason about in the abstract (eg, 2004 just means what it means). This isn’t always true, though, notably in the case of colors, where it’s impossible to reason in the abstract about which specific hexadecimal value you want to use. For example, I know that I want the democratic precincts to be “blue” and the republican precincts to be “red,” but I don’t know that I want to use #206bbf and #9d0000.

You could always just open one of the individual record forms, use the built-in color pickers to find a color that works well, and copy and paste it back into the stylesheet. This is sort of awkward, though. To fix this, Neatline makes it possible to just “activate” a set of styles for a tag in the stylesheet without providing a concrete value, and then set the value for the entire group of tagged records by making a change to an individual record.

We do this with the special auto value:

.democrat {
  fill-color: auto;
}

.republican {
  fill-color: auto;
}

Once this is in place, I can just open up any of the individual republican precinct records and pick a shade of red for that specific record. When I click “Save,” Neatline recognizes that the “Fill Color” style has been enabled for the republican tag, and that the record being saved is tagged as republican. When this happens, Neatline does two things. First, it updates the stylesheet with the new value:

.republican {
  fill-color: #9d0000;
}

And, second, it immediately propagates the new value to all of the other republican records, just as if the stylesheet had been directly saved. This actually works for all styles, even ones that already have concrete values in the stylesheet (as opposed to auto). For example, if I opened up one of the precinct records and changed the value of “Fill Opacity” to 0.7, and then saved that individual record, the fill-opacity rule under the precinct tag in the stylesheet would be updated with the new value and all of the precincts would be updated with the new value of 0.7. Effectively, this means that it’s impossible for the records and the stylesheet to get out of sync - changes made to the stylesheet are immediately propagated out to the records, and changes made to individual records are immediately pushed back into the stylesheet.

Here’s the complete stylesheet:

.precinct {
  fill-opacity: 0.5;
  stroke-width: 0;
}

.2000 {
  after-date: 2000;
  before-date: 2004;
}

.2004 {
  after-date: 2004;
  before-date: 2008;
}

.2008 {
  after-date: 2008;
  before-date: 2012;
}

.2012 {
  after-date: 2012;
  before-date: 2016;
}

.democrat {
  fill-color: #206bbf;
}

.republican {
  fill-color: #9d0000;
}