CSS Data Viewer Styling

From Grooper Wiki
(Redirected from Data Model Style Sheets)

This article is about the current version of Grooper.

Note that some content may still need to be updated.

2025 2023

Data Element Containers—including data_table Data Models, insert_page_break Data Sections and table Data Tables—support CSS-based customization via their Included Style Sheets and Style Sheets properties. This allows the appearance and layout of the Data Grid to be customized, enhancing the user experience during the person_search Review activity when using a Data Viewer.

Editor's note (revision pass): This article was last substantively verified approximately 3 years ago. Since then, Grooper has added several field types and Data Grid features not covered in the original text (Unrestricted List / combo-box fields, Multi Pick List / multi-choice fields, the Tabular View toggle on multi-instance Data Sections, and a set of CSS custom properties / theme variables for dark and light mode). This revision adds those sections, corrects the read-only field guidance (a long-standing product gap that was never documented here), and flags a couple of claims about caption markup that should be re-verified against current rendered HTML before being treated as authoritative. New or corrected content is marked inline with a [REVISED] tag; everything else is unchanged from the original.

About

CSS is a style sheet language used to define how HTML elements appear visually. CSS style sheets are ubiquitous in the world of web design and development. Fonts, headers, and container elements can be styled to make a web page more visually appealing and easier to read. This content is separated and formatted on a web page using a CSS file.

In Grooper, you can style your Data Model with custom CSS, changing how it appears during the Review activity (and previewed in the Design page). If you are using the Web Client, elements in your Data Model (Data Fields, Data Sections, etc.) are all rendered as some combination of HTML elements themselves when viewed over a browser. You can style how these elements are presented using CSS. This gives you a great deal of control over what you and your reviewers see in the Data Viewer during the Review activity.

FYI

The Review activity allows users to review various aspects of Grooper's automated document processing. What users review and how document content is presented is controlled by whichever Review Viewer UI the user is using.

  • Extracted document data is always reviewed using the Data Viewer interface.
  • All CSS styling done to your Data Model will be reflected to the user in the Data Viewer and only in the Data Viewer.
  • Because CSS styling only pertains to the Data Viewer, this article may use the terms Review Viewer and Data Viewer interchangeably.

Example Data View with no CSS

Example Data View with custom CSS

Data Elements are styled by editing a CSS file found on the Data Model.

  1. First select the Data Model you wish to style.
  2. You can then edit a CSS file using the Style Sheet property.
    • Press the ellipsis button at the end of the property to bring up the Style Sheet editor.


  1. Using the Style Sheet editor, you can enter as many CSS rules to style the Data Model as you need.
    • When possible, a CSS code completion window will pop up as you type, allowing you to select from a list of available elements, classes, properties, and certain values.


  1. CSS may also be edited at the Data Section and Data Table level.
  2. You will find these Data Elements also have a Style Sheet property.

Editing CSS at the Data Section and Data Table level can be particularly helpful when dealing with larger Data Models with multiple nested levels in their hierarchy. We will discuss this further in the Global Element Styling VS Local Element Styling section of this article.

CSS Basics

CSS styles webpage elements by defining a series of rules. Each rule defines how an HTML element looks: its text, its colors, its margins on the page, its alignment with other elements, and more.

In our case, the HTML elements we're working with correspond to our Data Model's Data Elements. The Data Fields, Data Sections, and Data Tables in the Data Model are rendered in a browser by a combination of HTML elements and their sub-elements. Each kind of Data Element has a corresponding customizable CSS class.


For example, when a user operates the Data Viewer in the Review activity and looks at a Data Field, they're really seeing three total HTML elements.

  1. A parent div element, with a DataField class.
  2. A child label element, corresponding to the Data Field's text label.
  3. A child input element, corresponding to the editable text box that holds the Data Fields extracted and/or user entered data.

[REVISED] This "three element" description is accurate for the Regular, Read Only, and Placeholder Text variants of a Data Field, all of which render as an input. It is not accurate for every Data Field configuration:

  • A Multiline field renders its value as a content-editable div, not an input.
  • A Restricted List field renders as a native select.
  • An Unrestricted List field renders as a <combo-box> custom element with several nested elements inside it.
  • A Multi Pick List field renders as a <multi-choice> custom element, also with nested elements.

See the new Field States section further down in this article for the full picture. The good news: regardless of which tag a field renders as, its value-holding element always carries a DataValue class, so most of the guidance in this article (which relies on .DataValue and .DataField) still applies uniformly. Just be aware that a rule written narrowly as input or .DataField input will silently skip multiline, list, and pick-list fields.


Each CSS rule consists of two parts:

  1. A selector.
    • This points to the HTML element you want to style.
  2. A declaration block.
    • This defines one or more style declarations, the specific ways you want the element to look.
    • Declaration blocks are surrounded by curly braces.
    • Multiple declarations are separated with semicolons.


Remember, a Data Field is represented in HTML as an element with two child elements:

  • A "label" element, representing the field's label.
  • An "input" element representing the entry value textbox (see the callout above for other possible value elements).

When styling Data Fields, it's important to understand which HTML element you want to style.

  • Do you want to style the Data Field's label? You'd use label as your selector.
  • Do you want to style the Data Field's input box? You'd use input as your selector (or .DataValue, which works regardless of the field's underlying tag — see below).
  • Do you want to style the larger element housing both the Data Field's label and input box? You'd use .DataField as your selector.


With no CSS applied, Data Models look pretty basic in the Review application. This is our blank canvas we start with. Using CSS, we can customize the look and feel of this user interface.

For example, say we want to change the font color and size of the Data Fields in our Data Model. We can do that with CSS. If we added the following CSS rule to our Data Model's Style Sheet, this would be the result:

label {
  color: rgb(248,148,32);
  font-size: 18px;
}

The selector label defines what element we want to style.

  • All label elements in the Data Viewer review panel.


The declaration block defines how we want to style the element.

  • color: rgb(248,148,32) changes the font color to "Grooper orange", using the RGB color value.
  • font-size: 18px changes the font's size to 18 pixels high.
  • Each declaration is separated from the next by placing a semicolon (;) at the end.

FYI [REVISED]

Grooper's Web Client ships with a set of built-in CSS custom properties (theme variables) for its color palette, including a "Grooper orange" variable. Instead of hardcoding rgb(248,148,32), this rule could be written as:

label {
  color: var(--grp-orange-1);
  font-size: 18px;
}

This produces the same color today, but will stay correct if the theme's exact orange value is ever adjusted, and will resolve to the correct shade in both dark mode and light mode automatically. See the new Using Theme Variables subsection under Color Styling for the full list of available variables and when to reach for them instead of a literal color value.


Notice the CSS rule only applied to what we told it to apply to: the Data Fields' labels.

No styling was applied to the:

  1. Data Field's input box.
  2. Data Section and Data Table caption text
    • Such as this label for the "Address Info" Data Section
  3. Data Table's Data Column header labels.

We would need to make separate CSS rules, selecting these corresponding HTML elements to style them as we wish.


FYI

Selector specificity is an important concept in CSS.


Technically, .DataField label is a more specific selector than just label. The selector .DataField label uses something called a "combinator" to select only child label elements under a parent HTML element with a DataField class. Therefore, it would prevent ambiguous selection of other label elements that are not children of DataField HTML elements.


However, due to how Grooper merges a Data Model's Style Sheet with the main Web Client's CSS file, you are generally safe simply using the label selector as a shortcut when you want to style all Data Field labels the same way.

A Common Example: Increasing a Data Field's Label Width

By default, a Data Field's input box is jammed right up against its label in the Data Viewer's screen. Nearly all Grooper users are going to want to space things out a little better. This will make the Data Model more readable, ultimately making your reviewers' job easier.

  • It's not just about making things "look good".
  • If the Data Model is easier to read, it's easier to understand. This makes the Review experience more efficient, ultimately making the process quicker and even preventing costly data entry errors.

A common CSS rule added to the Style Sheet will be one that increases the width of all Data Field labels.

  • Here, we've changed the CSS to increase the width of all Data Field labels in the Data Model to 140 pixels wide, using the following rule:
label {
  width: 140px;
}

Now, the label widths for all Data Fields have been lengthened to 140 pixels. As a result, the Data Model is much easier to read and interact when operating the Data Viewer during a Review activity.

Styling Scope: Selecting Data Elements

In the previous examples, we styled Data Field labels in a "global" manner. The CSS rule was applied to all Data Field labels in the Data Model. Sometimes we want to be more specific. We may want to narrow a rule's scope so it is applied to some elements, but not others.

Narrowing down the styling scope is done using one (or both) of the following methods:

  1. Selecting a specific Data Element using it's name.
    • For example, selecting and styling a Data Field named "Employee Name" rather than all Data Fields.
  2. Selecting a Data Element's children or sibling elements.
    • For example, selecting and styling Data Fields in a Data Section rather than all Data Fields.
    • This is done using what are called "combinators" in CSS.

Styling Named Elements

Imagine you have a specific Data Field you want to draw your users attention to. This may be a more "important" field according to some process if your organization that you really want them to pay attention to. One thing you could do is change the label's color to make it more distinct from the other fields in your Data Model.

To do this, you would select the specific element by name, rather than selecting all Data Fields.


Let's say "Employee Name" is a critical field for this Document Type's Data Model and we want to visually highlight that in some way during Review.

We're going to style just this Data Field with CSS. All we need to do is select the Data Field by name. Instead of using label as the selector, we will use the specific Data Field's name.

Specific data elements are selected simply by entering its name with any space characters replaced with underscores.

  • i.e. .Data_Element_Name

The following CSS rule makes only the "Employee Name" field's label appear orange.

.Employee_Name label {
  color: rgb(248,148,32);
}

FYI [REVISED]

An auto-generated name class like .Employee_Name is convenient, but if two Data Fields anywhere in a large Data Model happen to share the same display name, this class will match both of them. A custom CSS Class value set directly on the field (see Creating and Using CSS Classes below) is a more collision-proof way to target one specific field long-term, and is generally the better choice once a Data Model grows past a handful of fields.

Selector Specificity

Please note more specific rules always "win out". If multiple rules are written at larger or narrower scopes, the style rule with the narrowest scope will always be applied.

  1. This rule has a larger scope, applying to all Data Fields' labels.
    • The rule adjusts the label widths to 140 pixels wide and changes their color to "bisque".
label {
  width: 140px;
  color: Bisque;
}
  1. This rule has a narrower scope, applying only to the "Employee Name" Data Field.
    • The rule adjusts the label's color to orange.
.Employee_Name label {
  color: rgb(248,148,32);
}


Since .Employee_Name label is a more specific/narrower selector, its color styling is applied. The resulting text is orange and not bisque.

Also note the width declaration assigned using the larger scope label selector is still applied.

  • The .Employee_Name label declaration block said nothing about how to style the width.
  • Thus, the styling fell back on what was described by the label selector with the larger scope.

Selecting Multiple Elements

You can select and style multiple elements by creating a comma separated list of elements in the selector.


Let's say we wanted to make the "Employee Name", "Hire Date", and "Job Title" Data Fields' labels orange. We don't have to write out three separate CSS rules. Rather we can use a single rule, separating multiple selectors with a comma.

The CSS rule below will do the trick:

.Employee_Name label,
.Hire_Date label,
.Job_Title label {
  color: rgb(248,148,32);
}


You can also list elements horizontally, the two CSS rules below will operate identically.

Horizontal List

.Employee_Name label, .Hire_Date label, .Job_Title label {
  color: rgb(248,148,32);
}

Vertical List

.Employee_Name label,
.Hire_Date label,
.Job_Title label {
  color: rgb(248,148,32);
}

However, most would agree a vertical comma separated list of selectors is more readable.

Intro to Combinators

Styling child and sibling elements can be a great way to add more specificity to how you want to style various Data Elements in your Data Model. Child and sibling elements are selected in CSS using a "combinator".

A combinator explains the relationship between selectors. A combinator character is placed between selectors to define the relationship.

  • i.e. <element1><combinator><element2>

There are four combinators in CSS:

  •   - All descendant children selector
  • > - Immediate children selector
  • + - Adjacent (meaning "first immediately following") sibling selector
  • ~ - General (meaning "all following") sibling selector


We've actually already used a combinator in this article (the descendant children selector) when styling Data Field labels.

Remember, a Data Field is represented on webpages as an element that contains two child elements:

  • A "label" element
  • An "input" element


Earlier, we styled the color of the "Employee Name" Data Field's label using the following CSS rule:

.Employee_Name label {
  color: rgb(248,148,32);
}


The space character between .Employee_Name and label is the "descendant children selector". By selecting .Employee_Name label, we were selecting the child label elements of the Employee_Name element (i.e. the Data Field HTML element with the Employee_Name class).

This means two things:

  1. Any styling we applied was done not to the parent Employee_Name element (representing the whole "Employee Name" Data Field), but instead all descendant children label elements (representing the "Employee Name" Data Field's label).
  2. The only label elements selected were children of the Employee Name element. No other label elements were styled that way.


Combinators, like the descendant children selector, give us a variety of ways to craft highly specific selectors, leading to highly specific rules for a subset of elements.

FYI

While technically .DataField label selects all descendant label elements, .DataField elements only ever have one child label element.


Next, we'll look at other ways to use combinators.

Styling Descendant Child Elements

By far, the most common combinators you will likely use are the children combinators. This will allow you (among other things) to utilize Data Sections in ways to define styles for a particular collection of Data Elements distinct from the Data Model as a whole or Data Elements in other Data Sections.

  • The   (a single space character) selects all descendant children.
  • The > selects only immediate children.


Imagine you have a collection of Data Fields and Data Sections in your Data Model. Some Data Fields are at the root of the Data Model. Others are children of a Data Section.

Furthermore, imagine you want to style only Data Fields in a specific Data Section. We can do this with the descendant children ( ) and/or the immediate children (>) combinator.

For example, let's say we want to style all the Data Field label elements in the "Address Info" Data Section. We could use the following selector:

.Address_Info label

This uses the descendant children combinator to select all child Data Field HTML elements nested under the "Address Info" Data Section's HTML element.

  • The space character is actually doing something! It's not just there to look pretty. A space between HTML elements or class names will select all children elements of the given type at any descendant level in the parent element's hierarchy.
    • It doesn't matter if the child is at the first level below the parent, the second, the fifth or the fiftieth. For the descendant combinator , it will select them all.

Descendant Children Combinator

Say we want to recolor the labels for Data Fields in the "Address Info" Data Section. We can do that easily with the following CSS rule:

.Address_Info label {
	color: rgb(248,148,32);
}

See here, only the Data Fields in the "Address Info" Data Section had their label text colored orange.

The selector .Address_Info label, selected all child label elements in the .Address_Info element.

  • It is the space character ( ) between .Address_Info and label, dictating all descendant children should be selected.


Keep in mind, the descendant children combinator selects all children elements of the parent element. This may be what you want to do. It may not. It's important to realize what's going to happen, especially with larger Data Models with more complex Data Element hierarchies.

Let's say we want to style all Data Field labels in the "Personal Info" Data Section, including those in its child "Address Info" section.

  • The descendant children combinator ( ) is specifically designed for this situation.

The selector .Personal_Info label will travel down the HTML element hierarchy and select any label elements contained within the Personal_Info element.

The following rule colors all Data Field labels in the "Personal Info" Data Section orange.

.Personal_Info label {
  color: rgb(248,148,32);
}


Notice the "GUID" field and all fields in the "Previous Employment" Data Section are left unaffected. Why?

  • They are not children of the "Personal Info" Data Section.
  • Therefore, their HTML elements are not children of the Personal_Info class.
  • Therefore, their label elements are not selected by the selector (.Personal_Info label).


FYI

Due to how the descendant combinator works, the following selectors will behave identically.

  1. .Personal_Info label
  2. .Personal_Info .DataField label

Technically speaking, #2 is more specific.

  • It first selects all DataField elements that are children of the Personal_Info element.
  • Then, it selects all label elements that are children of the selected DataField elements.

In this case, the specificity is redundant. #1 functionally does the same thing.

  • It selects any child label elements in the Personal_Info element, including those that are children of DataField elements.

Styling Immediate Children Combinator

What if this isn't what you want to do? What if you don't want to select all descendant children, but only those that are at the root of an HTML element?

  • For example, what if you only want to style Data Field labels at the root of the "Personal Info" Data Section and leave any further descendant labels in the "Address Info" Data Section alone?
  • This is what the "immediate children" combinator (>) is for.


The immediate children combinator > selects a smaller scope of an element's children, namely only its immediate children.

We can use the immediate children combinator to select Data Fields that are immediate children of of the "Personal_Info" Data Section. Put another way, only Data Fields at the first level of the "Personal Info" Data Section will be styled.

  • The "Employee Name" Data Field is an immediate child. It will be styled.
    • So are "DOB", "SSN", and "Hire Date". They will be styled too.
  • The "Hire Date" and "Marital Status" Data Fields are immediate children. They be styled.
    • Just because they come after a Data Section sequentially doesn't mean they aren't immediate children. They are still in the first level of the "Personal Info" Data Section.
  • The fields in the "Address Info" Data Section ("Street Address" "City" "State" and "Zip") are descendant children further on down the object hierarchy. They will not be styled.
  • Fields outside the child scope, such as the siblings like the "GUID" Data Field and children of other elements such as the Data Fields in the "Previous Employment" Data Section, will also not be styled (just as they were not styled when using the descendant children selector).


Can we just swap combinators and use and use   instead of >? In other words, will this rule work?

.Personal_Info > label {
	color: rgb(248,148,32);
}

NO. Not quite. At least not in this case. This CSS rule would select nothing.

Why? The label HTML element is not an immediate child of the Personal_Info HTML element.

  • The label elements are desendant grandchildren of the Personal_Info element.
  • The label elements are children of the DataField elements.
    • This makes them descendant grandchildren of the Personal_Info element.
  • However, the DataField elements for Data Fields at the root of the "Personal Info" Data Section are immediate children.


We can use the following rule with the selector .Personal_Info > .DataField label to accomplish our goal:

.Personal_Info > .DataField label {
	color: rgb(248,148,32);
}

This rule will first select only immediate DataField children of the Personal_Info element. See this portion of the selector in bold below.

  • .Personal Info > .DataField label

Then, it will select all label children of DataField elements. See this portion of the selector in bold below.

  • Personal Info > .DataField label
    • FYI: Since a DataField's label element is itself an immediate child, .DataField > label would work identically.

As a result, only Data Fields at the root of the "Personal Info" Data Section are selected and have their labels colored.

FYI

The spaces on either side of the > combinator are simply added to increase readability.

The following selectors would work identically:

  • .Address_Info > .DataField label
  • .Address_Info>.DataField label


A Data Section is fundamentally a container for other Data Elements. Thus, DataSection elements only have five meaningful types of immediate children:

  1. A single h2 element with a caption class representing the Data Section's name.
  2. A div element with a DataField class representing any Data Fields in the Data Section.
  3. A div element with a DataTable class representing any Data Tables in the Data Section.
  4. A div element with a DataSection class representing any single instance Data Sections in the Data Section.
  5. A div element with a DataGridCollection class representing any multi-instance Data Sections in the Data Section.

Take extra care when styling elements in a Data Section and using the > combinator to ensure you select the correct immediate child first in your selector.

Styling Sibling Elements (Uncommon)

Less commonly, you may want to style sibling elements using the sibling combinators. This is a way of styling sibling Data Elements (existing in the same level of your Data Model's hierarchy) that come after a selected element.

  • The + selects "adjacent" siblings, selecting a single element after a specified element.
    • Put another way, the first instance of an element after a specific element.
  • The ~ selects "general" siblings, selecting any and all elements after a specified element.
    • Put another way, all instances of an element after a specific element.


For example, take the "Address Info" Data Section in the Data Model we've been using.

  • "Address Info" has a sibling relationship with all Data Elements at the same level in the Data Model.
  • "Address Info" has a parent-child relationship with every Data Element it contains.


There are two sibling Data Fields that follow the "Address Info" Data Section:

  • "Hire date"
  • "Marital Status"

The adjacent combinator + would allow us to select and style the first Date Field after the "Address Info" section. The general sibling combinator ~ would select and style all Data Fields after the "Address Info" section.

  • .Address_Info + .DataField will select only the first subsequent sibling DataField element.
    • Only "Hire Date" would be selected.
  • .Address_Info ~ .DataField will select all subsequent sibling DataField elements.
    • Both "Hire Date" and "Marital Status" would be selected.


For example, the following CSS rule uses the adjacent sibling selector.

.Address_Info + .DataField label {
	color: rgb(248,148,32);
}

Only the "Hire Date" Data Field's label is styled.


For example, the following CSS rule uses the general sibling selector.

.Address_Info ~ .DataField label {
	color: rgb(248,148,32);
}

Both the "Hire Date" and "Marital Status" Data Fields' labels are styled.

Styling Scope: Summary

For all cases below, you may presume an additional CSS rule has been added to adjust the label element widths to 140px.

Selection Type

CSS Rule

Selected Data Elements

Data Viewer Result


Generic element selection

label {
  color: rgb(248,148,32);
}

Selects every Data Field's label and colors it orange.


Named element selection

.Employee_Name label {
  color: rgb(248,148,32);
}

Selects only the "Employee Name" Data Field's label and colors it orange.


Descendant children selection

  •   combinator
.Personal_Info label {
  color: rgb(248,148,32);
}

Selects the Data Fields' labels for all children at every descendant level in the "Personal Info" Data Section and colors them orange.


Immediate children selection

  • > combinator
.Personal_Info > .DataField label {
  color: rgb(248,148,32);
}

Selects the Data Fields' labels only for children in the first level in the "Address Info" Data Section and colors them orange.


Adjacent sibling selection

  • + combinator
.Address_Info + .DataField label {
  color: rgb(248,148,32);
}

Selects the first sibling Data Field's label after the "Address Info" Data Section and colors it orange.

  • "Sibling" means the Data Elements are in the same hierarchical level of the Data Model.
  • "After" means following sequentially, in listed order from top to bottom.


General sibling selection

  • ~ combinator
.Address_Info ~ .DataField label {
  color: rgb(248,148,32);
}

Selects all sibling Data Fields' labels after the "Address Info" Data Section and colors them orange.

  • "Sibling" means the Data Elements are in the same hierarchical level of the Data Model.
  • "After" means following sequentially, in listed order from top to bottom.

Selector Quick Reference

Data Elements

Selector

What it selects

More information

.DataModel

Selects the Data Model

  • Selects the div that contains all HTML elements created to render a Data Model and its child Data Elements.

.DataField

Selects Data Fields

  • Selects the parent div that makes up a Data Field.
  • This div contains a label element and editable value element (See the "Editable value elements" section of this table for more).

.DataSection

Selects single-instance Data Sections and individual sections of multi-instance Data Sections.

  • Selects the parent div that makes up a single Data Section instance.
  • The div element's children with be made up of the Data Section's child Data Element's HTML elements.
  • [REVISED] If the Data Section is a multi-instance section currently switched to Tabular View, this selector still matches (see the new Tabular View section below), but several other selectors that normally target multi-instance records do not.

.DataGridCollection

Selects the container that houses multi-instance Data Sections

  • This is the parent div that houses all HTML elements formed when a multi-instance Data Section is extracted.
  • The div will contain one direct child div for each section instance extracted — unless the section is currently in Tabular View, in which case its single child is a virtual table rather than one div per record. See Tabular View below.

.DataGridCollection .DataSection

Selects all multi-instance Data Section instances.

  • Often, users want to style single-instance Data Sections and multi-instance Data Section records differently.
  • This will help you select only section instances formed by multi-instance Data Sections.
  • [REVISED] This selector matches in both Standard View and Tabular View, since both container types carry the DataSection class.

.DataTable

Selects Data Tables

  • Selects the parent div that houses all HTML elements used to render collected table data.
  • These children HTML elements include the table's caption label, its row of column header labels, each extracted row and each extracted cell.

.DataColumn

Selects header and value elements for Data Columns

  • Be aware: The DataColumn class selects two separate HTML elements that make up a Data Column.
  • It selects th elements that house a Data Column's header label.
  • It selects td elements that contain cell values for the table.
  • The header row and the scrolling body row are two separate HTML tables. A rule targeting one does not automatically reach the other — see the note under table styling below.

Labels and captions

Selector

What it selects

More information

label

Selects a Data Field's display label.

  • The label element is used to render a Data Field's display label. It is a child of the Data Field's div container.
  • Technically label.DataField is a more specific selector. Use this if label alone yields styling conflicts.

.caption

Selects a Data Section or Data Table's display label.

The caption class is applied to different HTML elements in the HTML hierarchy that form Data Sections/Data Tables.

  • For single instance Data Sections, an h2 element.
  • For multi instance Data Sections, a span element (inside the section's toolbar).
  • For Data Tables, a div whose child span actually contains the caption's text.
  • [REVISED — needs re-verification] These exact tag assignments were captured some time ago and have not been re-confirmed against current rendered HTML for this revision. If you need to target a caption's tag precisely (rather than relying on the tag-agnostic .caption class, which is the safer bet regardless), inspect the live markup first rather than assuming the tag breakdown above still holds exactly as described.

th.DataColumn

Selects Data Column display labels

  • The th element is used to display headers for each Data Column in a Data Table
  • Headers are housed in an HTML table (table.header) that has a single row (tr) with one th element for each Data Column.
  • The more generic th selector will probably work fine too. However,th.DataColumn is a more specific selector.
  • [REVISED] If the column belongs to a multi-instance Data Section currently in Tabular View, its header text is wrapped in a button inside the th — see Tabular View below.

Editable value elements

Selector

What it selects

More information

.DataValue

Selects all editable HTML elements.

  • The DataValue class is attached to every field/cell value control, regardless of what HTML tag it renders as — single-line inputs, multiline content-editable boxes, dropdown selects, and the two custom list elements described below.
  • Use this selector if you want to style all editable values of all types the same way; it is the single most reliable "style everything" hook in the Data Grid.

input

Selects default Data Field and Data Column inputs.

  • The input element is used to create an editable textbox for Data Field and Data Column values, for the Regular, Read Only, and Placeholder Text variants (single-line entry).
  • Use .DataField input to select only Data Field inputs (i.e. field values).
  • Use .DataColumn input to select only Data Column inputs (i.e. cell values).
  • Be aware multi-instance Data Sections use the input element for the editable number textbox in their navigation bar.
  • [REVISED] A Read Only field is still an input element, just with the HTML readonly attribute set — see Field States below for why input[readonly], not a class, is the selector you need.

div[contenteditable="true"]

Selects multiline Data Field and Data Column inputs.

  • A content editiable div is used to create a multiline editable textbox for Data Field and Data Column values. This is used when their "Multi Line" property is enabled.
  • Use .DataField div[contenteditable="true"] to select only Data Field multiline textboxes.
  • Use .DataColumn div[contenteditable="true"] to select only Data Column multiline textboxes.

select

Selects selection list Data Field and Data Column inputs.

  • The select select element is used to create dropdown selection lists for Data Field and Data Column values when the "Restricted" List Setting is used.
  • Use .DataField select to select only Data Field selection inputs.
  • Use .DataColumn select to select only Data Column selection inputs.
  • [REVISED] If the field's List Setting is Unrestricted or Multi Pick List instead of Restricted, it does not render as select at all — see the next two rows.

<combo-box> [REVISED — NEW]

Selects an "Unrestricted List" (searchable dropdown / autocomplete) Data Field or Data Column.

  • Renders as a custom element, not a native select. Contains a nested .combo-wrapper holding its own internal input, a dropdown toggle button, and a popup with .option rows.
  • These internals are plain, ordinary HTML — not shadow DOM. Target them with normal descendant selectors, e.g. combo-box.DataValue .combo-wrapper input. Do not use ::part() — it has no shadow boundary to cross here and will silently match nothing.
  • See Field States below for a confirmed side-by-side test of this.

<multi-choice> [REVISED — NEW]

Selects a "Multi Pick List" (checkbox-style multi-select) Data Field or Data Column.

  • Same pattern as <combo-box> above, but with a .multi-wrapper and .option rows that each contain their own checkbox input.
  • Same guidance applies: plain descendant selectors, not ::part().

.cell

Selects cells in a Data Table.

  • This is a handy class when you want to style cells of any type in a Data Table.
  • Because Data Table results are rendered with so many HTML elements, this is often the simplest, most efficient and easiest to remember selector to use.
  • [REVISED] A multi-instance Data Section's fields switched to Tabular View lose this .cell class even though they otherwise render inside a table-like structure — see Tabular View below. A rule relying only on .cell will not reach Tabular View cells.

Other elements

Selector

What it selects

More information

datalist

Selects the Auto Complete box (when enabled).

  • Only used when a Data Field or Data Column's "Auto Complete" property is enabled.
  • The datalist element is used to render the autocomplete list.
  • Not commonly used or styled

option

Selects options in the Auto Complete box (when enabled).

  • Only used when a Data Field or Data Column's "Auto Complete" property is enabled.
  • The option element is used to render items in the autocomplete list.
  • Not commonly used or styled
  • [REVISED] Don't confuse this with the .option class used inside the <combo-box>/<multi-choice> dropdown popups described above — those are a different, unrelated element serving a similar-sounding purpose for a different field type.

Field States: Read-Only, Required, Lists, and Other Dynamic States [REVISED — NEW SECTION]

A Data Field or Data Column's underlying HTML can change shape depending on its configuration and, in some cases, its current state. This section covers the states not addressed elsewhere in this article: read-only fields, required/invalid fields, the two list-type custom elements, and a few other state classes worth knowing about.

Read-Only Fields

Known product gap: Grooper's built-in stylesheet includes a rule intended to dim read-only fields, roughly equivalent to .DataValue.readonly { color: #999; }. However, a field marked "Read Only" in Grooper does not get a readonly class in its rendered HTML — it gets the native HTML readonly attribute instead. Because the built-in rule is looking for a class that never actually appears, it currently matches nothing, and read-only fields render visually identical to regular editable fields unless you add your own rule.

To style read-only fields yourself, use an attribute selector instead of a class selector:

input[readonly].DataValue {
  color: #999;
}

This reliably catches every read-only single-line field model-wide. (If Grooper adds the missing class in a future version, both this attribute selector and a hypothetical .readonly class selector would work side-by-side without conflict.)

Required / Invalid Fields

There is no static, always-visible CSS class marking a field as "required." Grooper only exposes a live failure state: while a required field currently has no value (or an otherwise invalid value), it gains an invalid class and a data-error attribute describing the problem. The moment a valid value is entered, both disappear.

input.invalid {
  border: 2px solid red;
}

Practical implications:

  • You can style "currently failing validation" — target .DataValue.invalid.
  • You cannot use CSS alone to put a permanent marker (like an asterisk) on a required field that a user simply hasn't gotten to yet. That would require a static class Grooper doesn't currently generate.
  • If you're asked to remove or soften the default red invalid-state styling, that's a reasonable request to fulfill, but it's worth mentioning to whoever's asking that this also removes a visible validation cue for reviewers.

Unrestricted Lists and Multi Pick Lists (Custom Elements)

Two list-type field configurations don't use a native <select> at all:

List Setting Rendered element Internal structure
Unrestricted (searchable dropdown / autocomplete) <combo-box> A nested .combo-wrapper containing its own input, a dropdown toggle button, and a popup of .option rows.
Multi Pick List (checkbox-style multi-select) <multi-choice> A nested .multi-wrapper with the same general shape, but each .option row also contains its own checkbox input.

Both are true custom elements, which might suggest they use the browser's shadow DOM (where you'd normally need special ::part() selectors to reach inside). They don't. A direct side-by-side test confirmed this: two competing rules were added to a Style Sheet, one using a plain descendant selector and one using ::part(), both targeting the same internal input with an unmistakable color change. The plain descendant selector took effect; the ::part() rule did nothing.

/* This works: */
combo-box.DataValue .combo-wrapper input {
  background-color: rgb(255, 255, 200);
}

/* This does NOT work — there is no shadow boundary here for ::part() to cross: */
combo-box.DataValue::part(input) {
  background-color: rgb(255, 255, 200);
}

Use plain attribute/descendant selectors for anything inside a <combo-box> or <multi-choice> element.

Other State Classes Worth Knowing

Class When it appears Notes
.confirmed Applied when a user runs the "Confirm" command on a field that's currently in an error/invalid state, to manually mark it as validated. Only stylable, not triggerable from CSS.
.highlight Applied by the Data Grid's built-in "search field values" searcher (top of the Data Grid) to mark text matches. Only stylable, not triggerable from CSS.

Types of Styling Available

There is A LOT you can do with CSS. There's far too much for us to cover completely. However, there are a few common types of styling you may want to apply to your Data Model.

In this section, we will detail some basic examples as they relate to the following categories:

Font and Text Styling

Font and text formatting are some of most basic, but also most important, considerations when building a website. We will review a few of the standard CSS properties that can alter the text labels in a Data Model.

Keep your eye on the "Hire Date" field. Each of the CSS rules we demonstrate will affect its field label.

Font Size

The font-size property will adjust the size (height) of the font. Font size can be adjusted using absolute values or relative values.


Using the CSS rule below, we've adjusted the "Hire Date" field's label absolutely, setting it to a specific value (21px).

.Hire_Date label {
  font-size: 21px;
}


You can also set the font size relatively by setting the font size as a percent or with an "em" value.

  • 1em = the current font size. Therefore 0.5em = half the current font size. 2em = double the current font size. And so on.
  • Many developers prefer to use relative sizing as it tends to work better across all browsers and consider using em values to be best practice.

The default size of Data Field labels is set to 14px in Grooper. Therefore, the following CSS rules should produce identical results:

.Hire_Date label {
  font-size: 21px;
}
.Hire_Date label {
  font-size: 1.5em;
}
.Hire_Date label {
  font-size: 150%;
}

Font Style (Italics)

The font-style allows you to italicize text.


The CSS rule below italicizes the "Hire Date" field.

.Hire_Date label {
  font-style: italic;
}


The font-style property may be set to one of the following:

  • normal
  • italic
  • oblique

If no italic or oblique face for the font is available, the browser will attempt to mimic the sloping effect. If italic is selected, but there is no italic face for the selected font, the browser will attempt to use the oblique face before mimicking effect (and visa versa if oblique is selected).

FYI

What's the difference between italic and oblique? Good question. The short answer is "not much".

  • Officially, “Italic forms are generally cursive in nature while oblique faces are typically sloped versions of the regular face.”
  • For most fonts, there is little to no difference between italic and oblique faces.

Font Weight (Bolding Text)

The font-weight property allows you to bolden or lighten text (when available).


The CSS rule below bolds the "Hire Date" field.

.Hire_Date label {
  font-weight: bold;
}


The font-weight property may be set to one of the following:

  • normal
  • bold
  • bolder
  • lighter

If selected and the font being used has a "bold" or "normal" version, the browser will use that. If not, it will attempt to mimic a bold or normal version. The browser will not attempt to mimic a "lighter" or "bolder" version if none are found.

Font Variant (Small Caps)

The font-variant property allows you format your text in small caps.


The CSS rule below turns the "Hire Date" field to small caps.

.Hire_Date label {
  font-variant: small-caps;
}


The font-variant property may be set to either of the following:

  • normal
  • small-caps

Font Families

The font-family property sets what font family should be used to render the text.


The CSS rule below changes the "Hire Date" field from the default font (Open Sans) to Courier New.

.Hire_Date label {
  font-family: Courier New;
}

Be aware a font will only display if it is installed by the browser or on the device viewing the webpage. The following fonts are considered "web-safe". These are fonts universally installed by all browsers.

(Generally) Web-Safe Fonts

  • Arial (sans-serif)
  • Verdana (sans-serif)
  • Tahoma (sans-serif)
  • Trebuchet MS (sans-serif)
  • Times New Roman (serif)
  • Georgia (serif)
  • Garamond (serif)
  • Courier New (monospace)
  • Brush Script MT (cursive)


However, there are no 100% web safe fonts. While these are "universally" installed across "all" browsers, there's always a chance the font is not installed properly or is otherwise missing. That's why it's best practice to use a fallback font.

  • Fallback fonts are separated using a comma.
  • For example: font-family: Tahoma, Verdana, sans-serif;
    • The browser would first attempt to use Tahoma.
    • If that font cannot be found, it then attempts to use Veranda.
    • If that font cannot be found it will use the generic system sans-serif font for the browser.


AT BARE MINIMUM, you should always include one of the following generic fallback fonts when declaring a font family:

  • sans-serif
  • serif
  • monospace
  • cursive
  • fantasy

Text Alignment

The text-align property allows you to set an alignment for text inside the element.


The CSS rule below right aligns the "Hire Date" field's text within its label element.

.Hire_Date label {
  text-align: right;
}


You may choose one of the following alignments:

  • left (This is the default, in most cases)
  • right
  • center
  • justify

Text Color

As we've seen in previous examples, the color property styles the element's text content's color.


Using the CSS rule below, we've adjusted text color for the "Hire Date" field's label, using the RGB color value for "Grooper orange".

.Hire_Date label {
  color: rgb(248,148,32);
}

FYI [REVISED]

As mentioned earlier, this could also be written as color: var(--grp-orange-1); to reuse Grooper's built-in brand color variable instead of hardcoding the RGB value. See Using Theme Variables below.

Colors can help draw a user's attention and separate content in meaningful ways. There's also more to coloring a webpage than just coloring text. We'll talk more about color styling in the Color Styling section of this article.

Font and Text Styling Summary

Text Style

CSS Rule

Selected Data Elements

Data Viewer Result


Font size

.Hire_Date label {
  font-size: 21px;
}

Increases the "Hire Date" Data Field's font size to 21 pixels high.


Font style (italics)

.Hire_Date label {
  font-style: italic;
}

Italicizes the "Hire Date" Data Field's label.


Font weight (bolding text)

.Hire_Date label {
  font-weight: bold;
}

Bolds the "Hire Date" Data Field's label.


Font variant (small caps)

.Hire_Date label {
  font-variant: small-caps;
}

Turns the "Hire Date" Data Field's label to small caps.


Font families

.Hire_Date label {
  font-family: Courier New, monospace;
}

Changes the "Hire Date" Data Field from the default font (Open Sans) to Courier New. If Courier New cannot be rendered, the system monospace font will be used as a fallback font.


Text alignment

.Hire_Date label {
  text-align: right;
}

Right aligns the "Hire Date" Data Field's text within its label element.


Text color

.Hire_Date label {
  color: rgb(248,148,32);
}

Changes the "Hire Date" Data Field's label's text color to "Grooper orange", using the RGB color value.

FYI: Styling Data Section and Data Table Caption Labels

Styling Data Section and Data Table Caption Labels

A Data Section or Data Table's header caption is itself just another child element rendered on a webpage. All Data Section and Data Table HTML elements have a child element with a caption class styling their caption in the Review screen.

When it comes to styling Data Section and Data Table captions, you'll need to use the .caption selector. This will select any element with the caption class — this is intentionally tag-agnostic, so it works no matter which specific tag a given caption happens to render as (see the caveat in the Selector Quick Reference table above about the exact tag breakdown needing re-verification).


All captions will be styled if you simply use .caption for the CSS rule's selector, as in the rule below:

.caption {
  color: rgb(248,148,32);
  font-size: 1.5em;
  font-variant: small-caps;
}

FYI

For more specific caption styling, use more specific CSS selectors.


You can also remove a caption by using the display: none; declaration.

  • This can be useful if you need to place fields in a Data Section for data extraction or Batch processing purposes, but would confuse or distract users.

For example, adding the following CSS rule would remove the caption for the "Address Info" section.

.Address_Info .caption {
  display: none;
}

See here, the "Address Info" caption has been entirely removed in the Review viewer.

  • As far as the reviewer is concerned, there is no "Address Info" section. But, you the Grooper designer knows better!

Margins, Borders, Padding, Height and Width Styling

There's good reason why a div HTML element is named so. A div creates a division within a document, making it more distinct from other elements on the webpage. Margins, borders and padding help make the divisions between HTML elements visually more distinct by increasing the space between the elements (margins), outlining the elements (borders) and increasing the space within an element (padding).

Effective use of margins, borders and padding can increase the readability and accessibility of your Data Model when viewed in a Review viewer.

The Box Model

If you've spent any amount of time with CSS, you've probably seen the "Box Model".

This diagram is designed to help you better understand the different dimensions of an HTML element, including:

  • The content's width and height
  • The padding size
  • The border width
  • The margin size


When styling an element you can use the margin, border, padding, height, and width properties to better space out and define different elements.

As this pertains to styling Data Elements, this can help make your Data Model more readable and better help create logical section divisions in the Review viewer.

FYI

Adjusting the margin, border, and padding values will adjust these properties on all four sides (top, bottom, left and right) with the same measurement.

You can specifically adjust one side's value by adding -top, -bottom, -left, or -right to the property, depending on which side you want to adjust.

  • For example, margin-left would only adjust the left margin, leaving the top, bottom and right margins alone.

Margins

The margin properties adjust the space between HTML elements.


One practical use of margins is to effectively indent Data Elements to better define sections of fields in the Review viewer.

This CSS rule, indents all Data Sections by increasing the left margin value.

.DataSection {
  margin-left: 32px;
}
  1. See here, the "Personal Info" Data Section is now indented.
    • There is now 32 pixels of whitespace on the left boundary of the element.
  2. The "Address Info" Data Section also has its left margin increased by 32 pixels.
    • Note since this Data Section is a child of another Data Section, its HTML DataSection is contained within another DataSection element.
    • Therefore, it is indented 32 pixels from within its parent container.
  3. The section records within the multi-instance "Previous Employment" Data Section have their left margin increased by 32 pixels.
    • Multi-instance Data Sections are represented as HTML elements with the DataGridCollection class. Each of its section record in a multi-instance Data Section is represented as a DataSection HTML element.
    • Therefore, the section record is indented 32 pixels from within the parent DataGridCollection element.


FYI

Margin specifications are often used to center HTML elements. If you're trying to center an entire element (not the text within an element, but the element itself), try using the following two declarations:

margin-left: auto;
margin-right: auto;

Borders

The border property creates a stroked border around the HTML element. When defining the border property, you can control the border's width, style (e.g. "solid" or "dashed"), and color.

Borders are another way of visually separating content. When used to style Data Sections and Data Tables, this can better divide out the Data Elements within your Data Model.


Borders are always are always defined by specifying at least the border's width and style. Most typically, you will also specify the border's color.

For example, the CSS rule below draws a solid white border around all Data Tables.

.DataTable {
  border: 1px solid rgb(255,255,255);
}

The border property definitions determine how the border looks.

  • 1px - This makes a border 1 pixels in width.
  • solid - This makes a solid border (as opposed to a dotted or dashed one).
  • rgb(255,255,255) - This colors the border white, using its RGB color value.


Once you start adding borders to elements in your Data Model, the margin, padding, height and width properties become even more important. This is particularly the case when adding borders to Data Section elements.

Using the CSS rule below, we've added a solid 1 pixel border around all Data Sections.

.DataSection {
  border: 1px solid rgb(255,255,255);
}

As it stands, having a border around Data Sections doesn't visually improve the Data Model. This doesn't really do anything to improve the users experience in Review and is actually a little confusing to look at. Why does it look the way it does? There is effectively no padding specified here.

Next, we will add some padding to these elements to vastly improve the Data Sections' styling.

FYI

Single instance Data Sections are rendered in HTML as a div container with a DataSection class.

  • The single DataSection element contains any child Data Elements as child HTML elements.
  • "Personal Info" and "Address Info" are single instance Data Sections in this image.

Multi instance Data Sections are rendered in HTML as a div container with a DataGridCollection class.

  • The single DataGridCollection element contains one or more DataSection child HTML elements, one for each section instance produced.
  • These multiple DataSection HTML elements then contain any of the Data Section's child Data Elements as child HTML elements.
  • "Previous Employment" is a multi-instance Data Sections in this image.
  • [REVISED] This is the Standard View rendering of a multi-instance section. See the new Tabular View section below for how this structure changes when a user switches the section to its alternate grid-style view.

Padding

The padding properties adjust the space around the HTML element, between the element and any defined border. Another way of thinking about padding is it extends the height and/or width of the element.

Padding is almost always specified when adding a border to an element. Without any padding, the border butts right up to the boundaries of the element's content. This can be visually jarring and confusing. The extra padding helps increase readability by adding some "breathing room" between the element's content and its border.


By adding just a little padding around our Data Section elements, we can start to see the benefits of adding a border.

Below, the CSS rule adds a 1 pixel border around Data Sections and increases their padding by 12 pixels on all sides.

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
}

See here, the space between the element and the border are better spaced out. 12 pixels have been added to the top, bottom, left and right edges to the element, between the 1 pixel wide solid border.

Bonus! Border Radius

If you prefer the look of rounded boxes, you should use the border-radius property.

This is the same CSS rule with a border-radius declaration added. This rounds out the border's corners using a 4 pixel radius.

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
  border-radius:4px;
}


Next, we're going to visit the height and width properties to further style the look of our Data Sections.

Height and Width

Aside from adjusting margins and padding to space out an element, it can be beneficial to adjust the element's actual width and height. This can be done with height and width properties (as well as min-height/max-height and min-width/max-width).

Width and height specifications are often adjusted to better adjust a webpage's layout by adjusting the dimensions of the HTML elements that make up that webpage. For example, Grooper users will commonly adjust the Data Field label elements' width (See above for illustration).


Once you start using CSS to customize the layout of Data Elements in the Data Viewer, you may find you need to adjust the widths and heights of Data Elements, such as your Data Sections. By default, Data Field, Data Section, and Data Table HTML elements take up the entire width of available horizonal space in the Data Viewer. With borders clearly marking the boundary of an element, this is a lot more noticeable.

The CSS rule below adjusts the maximum width of all Data Sections. It specifies Data Sections can only be at maximum 400 pixels wide by adding a max-width specification.

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
  border-radius: 4px;
  max-width: 340px;
}


Why did we use the max-width property instead of the width property? The width property sets a literal width. The max-width property is more dynamic. Elements' widths will be adjusted up to a maximum value.

In our case, one of our Data Sections is a child of another data section. If we used the CSS rule below, using the width property, the result would be less ideal in this case.

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
  border-radius: 4px;
  width: 340px;
}

There are plenty of circumstances in which the literal width specification would be appropriate. It just was not as appropriate here.

  • Given one Data Section element is a sub-element of another Data Section, using the max-width property allows the child Data Section to be dynamically resized to fit within the parent Data Section.

A Width You Can't Adjust With CSS

There is one element width you cannot adjust with CSS, an input element's width.

To adjust the width of a Data Field or Data Column's input box, you must use the Display Width property in the object's property grid.

  1. Select the Data Field or Data Column whose input box you wish to adjust.
  2. Enter the width (in pixels) in the Display Width property.
  3. The input box's width will be adjusted to the entered value.

Margins, Borders, Padding, Height and Width Summary

Style Description

CSS Rule

Selected Data Elements

Data Viewer Result


Margins

.DataSection {
  margin-left: 32px;
}

Adds 32 pixels to all Data Sections' left margin. Effectively, this left indents all Data Section elements 32 pixels.

  • Note the "Address Info" Data Section is a child of the "Personal Info" Data Section, and thus a sub-element of the Personal_Info HTML element.
    • Therefore, the "Address Info" section is indented 32 pixels from inside the "Personal Info" section.
  • Note only the Data Fields were indented 32 pixels for the "Previous Employment" Data Section (not, for example, the "Previous Employment" caption).
    • This is because "Previous Employment" is a multi-instance Data Section. For multi-instance Data Sections, each section instance is represented by a DataSection element housed in a parent DataGridCollection element.


Borders

.DataSection {
  border: 1px solid rgb(255,255,255);
}

Outlines all Data Sections with a white 1-pixel wide border.


Padding

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
}

Outlines all Data Sections with a white 1 pixel wide border. Adds 12 pixels of padding between the element's content and the border.


Border Radius

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
  border-radius: 4px;
}

Outlines all Data Sections with a 1 pixel wide border. Adds 12 pixels of padding between the element's content and the border. Rounds the corners on the borders.


Width

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
  border-radius: 4px;
  width: 400px;
}

Outlines all Data Sections with a white 1 pixel wide rounded border. Adds 12 pixels of padding between the element's content and the border. Sets the literal width of all Data Section elements to 400 pixels wide.


Max Width

.DataSection {
  border: 1px solid rgb(255,255,255);
  padding: 12px;
  border-radius: 4px;
  max-width: 400px;
}

Outlines all Data Sections with a white 1 pixel wide rounded border. Adds 12 pixels of padding between the element's content and the border. Sets the maximum width of all Data Section elements to 400 pixels wide.

FYI [REVISED]

Because the header row and the scrolling body of a Data Table are two separate HTML tables (see the Selector Quick Reference table above), a margin/border/padding rule aimed at a Data Column generally needs to address both halves separately if you want header and body cells to look consistent, e.g.:

.DataTable table.header th { /* header cell styling */ }
.DataTable table.dgt-table td { /* body cell styling */ }

Color Styling

Colors are useful in a variety of different ways. They don't just "look pretty". They're used to call attention to different portions of a document, divide sections on a document, or distinguish between portions of a document.

There are a lot of ways you could style elements' colors in HTML (and therefore Data Elements in Grooper's Data Viewer). We're going to focus on the three most common ways colors are styled:

  • Text colors
  • Border colors
  • Background colors

First, how do you pick a color? How do you define whether something is red or blue or hot pink? There are a few different ways to define a color value in CSS.

Specifying Colors

You can specify colors in CSS in the following ways:

#FFF8DC

Hexadecimal colors

  • Ex: #FFF8DC is the color known as "cornsilk".

#FFF8DC50

Hexadecimal colors with transparency

  • Ex: #FFF8DC50 is cornsilk with a 50% transparency.
  • The last two numbers (e.g. #FFF8DC50) set the transparency transparency value on a scale from 00 to FF.
    • 00 indicates full transparency. FF indicates full opacity. Anything from 01 to 99 is a percentage value in between.

rgb(255, 239, 213)

RGB colors

  • Ex: rgb(255, 239, 213) is the color known as "papaya whip".
  • Colors in the RGB color model are defined by their intensity values (from 0 to 255) of red, green and blue light.

rgba(255, 239, 213, .5)

RGBA colors

  • Ex: rgba(255, 239, 213, .5) is papaya whip with a 50% transparency.
  • RGBA colors use the RGB color model with an additional alpha channel. The alpha channel (e.g. rgba(255, 239, 213, .5)) sets the color's transparency/opacity.
    • This sets the opacity value on a scale from 0 (fully transparent) to 1 (fully opaque).

hsl(36, 100%, 84%)

HSL colors

  • Ex: hsl(36, 100%, 84%) is the color known as "Navajo white".
  • The HSL color model is an alternative to the RGB color model designed by computer graphics researchers in the 1970s to more closely correlate color values to how the human eye perceives color. It represents colors based on their hue, saturation and brightness values.

hsla(36, 100%, 84%, .5)

HSLA colors

  • Ex: hsla(36, 100%, 84%, .5) is Navajo white with a 50% transparency.
  • HSLA colors use the HSL color model with an additional alpha channel. The alpha channel (e.g. hsla(36, 100%, 84%, .5)) sets the color's transparency/opacity.
    • This sets the opacity value on a scale from 0 (fully transparent) to 1 (fully opaque).

BurlyWood

Predefined color names used across browsers

  • Ex: BurlyWood is the color known as "burlywood".
  • You can find a list of color names supported across browsers here.


FYI

Which color space should you use? Generally speaking it's up to you.

In this article, you will find we most often use the RGB and RGBA color spaces.

  • We use RGB for literal color definitions when we know the exact color value we want something to be.
  • We use RGBA when we want to shade or tint an existing color, starting with black or white as our color value and adjusting the alpha channel transparency between 0 to 1 until we find the right color.
    • This is often useful to keep colors consistent within a monochromatic or semi-monochromatic color scheme.

Using Theme Variables Instead of Hardcoded Colors [REVISED — NEW SUBSECTION]

Everything above is standard CSS and still works fine in Grooper. However, the Web Client's built-in stylesheet now defines a set of reusable CSS custom properties (theme variables) for its dark-mode and light-mode color schemes. Wherever you want a color to "fit the existing theme" rather than be a fixed, specific color, referencing one of these variables is usually a better choice than hardcoding a hex or RGB value — the same rule will then automatically resolve to the correct shade whether the user is in dark mode or light mode, and will stay correct if Grooper ever adjusts its exact color values.

Need Variable(s)
Primary / brightest text var(--text-primary)
Secondary / dimmer text var(--text-secondary), var(--text-subsecondary), var(--text-disabled)
Brand accent (teal) var(--grp-teal-1), var(--grp-teal-2), var(--grp-teal-3)
Brand accent (orange) var(--grp-orange-1)
Error / danger state colors var(--color-danger-bg), var(--color-danger-fg), var(--color-danger-border)
Warning color var(--color-warning-fg)
Default input background/border var(--input-bg), var(--input-border)
Subtle borders/backgrounds at increasing opacity var(--fg-color-05) through var(--fg-color-50)
Corner rounding scale var(--border-radius-1) (4px), var(--border-radius-2) (6px), var(--border-radius-3) (8px)

For example, the "highlight a critical field" rule from earlier in this article could be written either way:

/* Fixed color, same result in every theme */
.Employee_Name label {
  color: rgb(248,148,32);
}

/* Theme-aware — resolves to Grooper's current brand orange in whatever theme is active */
.Employee_Name label {
  color: var(--grp-orange-1);
}

FYI

Only reach for a hardcoded color when the request genuinely calls for one specific, theme-independent color (for example, "make this field bright red no matter what," or a customer's own brand color that has nothing to do with Grooper's theme). For anything meant to blend in with Grooper's existing look and feel, prefer the variables above.

Text Color

We've already seen text color styling in this article, using the color property. The color property change the text's color within an element.

For example, this CSS rule will color the "Employee Name" Data Field's input box text yellow.

.Employee_Name input {
  color: rgb(255,255,50);
}

Something like this can be useful for a Data Field value that needs highlighting. If a user has a need to keep referencing an extracted value, this will more clearly call it out in the Review viewer.

Border Color

You can style a border's color using either the border-color or border property.

If the HTML element already has a border specification, you can use the border-color property to recolor the border.

This CSS rule recolors the border around the "Employee Name" Data Field's input box.

.Employee_Name input {
  border-color: rgb(248,148,32);
}

Please note, if the element doesn't already have a border specified (either from an inherited class or in the CSS rule itself), the border-color property will do nothing. There is no border to color at that point.


You can use the border property as a shortcut to create a border, setting the width, style and color all with a single property.

The first description line in the following CSS rule creates the border, including coloring it orange with the RGB color rgb(248,148,3,)

.DataSection {
  border: 1px solid rgb(248,148,32);
  border-radius: 4px;
  padding: 12px;
  padding-top 8px;
  margin-top: 8px;
  margin-bottom: 8px;
}

Background Color

Text is considered the "foreground" of an HTML element. Whatever is behind it counts as "background". The background-color property (appropriately enough) colors an element's background. Coloring an element's background can be a great way of drawing attention to certain Data Elements or making visual breaking points between groups of Data Elements.

This CSS rule colors the background of the "Employee Name" Data Field's input box yellow. This is another way to make an important field stand out from others.

.Employee_Name input {
  background-color: rgb(255,255,50);
  color: rgb(0,0,0);
}

Notice we also changed the text color to black (color: rgb(0,0,0)). If we did not, the text would have been unreadable on a yellow background.

  • Be aware once you start styling background colors, you may need to style other colors (particularly text colors) in order to make your Data Model more readable in the Review viewer.


Background color styling is also a way to make your Data Sections distinct.

We're using the following CSS rule to style our Data Sections.

.DataSection {
  background-color: rgba(0,0,0,.25);
  border: 1px solid rgba(255,255,255,.5);
  border-radius: 4px;
  padding: 12px;
  padding-top 8px;
  margin-top: 8px;
  margin-bottom: 8px;
}

The first description (background-color: rgba(0,0,0,.25))colors the Data Sections' backgrounds.

We're also using RGBA alpha channel here.

  • The rule colors the background of all Data Sections black with a 25% transparency. Effectively this slightly shades Data Sections.
  • Because the "Address Info" Data Section is nested within the "Personal Info" Data Section it is extra shaded! Its black transparency is overlaid on top of the already darkened background behind it.

The combination of borders, padding and color shading really separates these Data Sections from the rest of the Data Model.


FYI

Please be aware any padding in an element is considered part of the element's background. Margins are space outside the element and are not part of the element's background.

  • Space specified by padding will be colored by a background-color specification.
  • Space specified by margins will not be colored by a background-color specification.

Layout Styling

Without CSS, you'd have no control over how Data Elements are laid out in the Data Viewer. They would appear on the screen essentially as a list, with each Data Field occupying a single line. However, CSS rules give you a great deal of flexibility in terms of laying out the various elements that make up the Data Elements in your Data Model.

With a few simple adjustments to properties like margins, borders, and an element's display mode, you can re-order your Data Model's layout to make a better review experience.

FYI [REVISED]

Before writing custom layout CSS from scratch, it may be worth checking whether Grooper's built-in indent, card, or compact layout presets already get you what you want. These are plain CSS classes already defined in Grooper's base stylesheet — typing one of these words into a Data Model's CSS Class property applies a pre-built layout for free, without writing a single line of custom CSS. They're a good starting point even if you plan to layer additional custom rules on top.

Generic Layouts

In the Generic Layout Examples section of this article, you will find some generic layout examples that could be applied to any content model.

These include:

  • List Layout - Styles fields and sections as a simple list. Hierarchy in Data Elements is defined by indenting Data Elements in Data Sections.
  • Flow Layout - Lists fields horizontally rather than vertically, stacking labels on top of their input boxes. Fields will wrap to fit the Data Grid or Data Section they are contained within.
  • Card Layout - Relies on Data Sections and border styling to create distinct divisions between different kinds of fields on the document. Each Data Section becomes a "card" with a list of fields on it. The fields in each card can be styled with either a list or flow layout.

Tabular View: A Note on Multi-Instance Data Sections [REVISED — NEW SECTION]

Every multi-instance Data Section has a view-mode toggle in its toolbar (an icon button, sometimes reachable via Alt+T) that switches the section between its normal record-by-record layout ("Standard View," the only mode this article otherwise describes) and a spreadsheet-style "Tabular View" where every record becomes a row in a single virtual table.

This matters for CSS because toggling the view mode doesn't add a class to the existing container — it swaps in a differently-structured element entirely. Rules written only with Standard View in mind can silently stop working the moment a reviewer switches a section to Tabular View.

Standard View (the default assumed elsewhere in this article) Tabular View
Container element div with DataGridContainer, DataSection, and multi classes, one per record A single div with VirtualTable and DataSection classes (no multi, no per-record repetition)
Row-level markup Fields laid out directly, no table structure A table.header / table.dgt-table split-table structure, similar to a real Data Table
Row class (n/a — each record is its own container) tr.VirtualTableRow, not tr.DataGridRow
Body cell class Same as any Data Field: DataValue DataField-style structure Drops the .cell class that a real Data Table's body cells carry
Column headers Plain text in the header row Header text is wrapped in a button (which also triggers column sorting when clicked)

Practical takeaway: bulk rules built around .DataValue, .DataSection, or .DataColumn keep working in both view modes, since those classes are shared by both structures. But any rule that specifically targets .DataGridContainer, .multi, .DataGridRow, .cell, or .DataGridTable will only reach Standard View — it will quietly do nothing while a section is switched to Tabular View. If you need a rule to apply consistently in both modes, you'll typically need a second, parallel selector aimed at the Tabular View's equivalent classes (.VirtualTable, .VirtualTableRow, etc.) in addition to the Standard View one.

There's no way to detect which view mode is currently active using CSS alone — nothing in the DOM changes except the toggle button's own icon — so a stylesheet author should generally just plan for a rule to be visible/applied correctly in either mode rather than trying to target one specifically.

Tips and Best Practices

Two Approaches: Global Element Styling VS Local Element Styling

Be aware you can style a Data Model in two ways:

  1. Globally - By editing the Data Model's Style Sheet.
  2. Locally - By editing any children Data Sections' or Data Tables' Style Sheets.
    • Styling a Data Section or Data Table's Style Sheet directly, simply limits the scope of accessible elements.

GLOBAL STYLING

(Data Model)

When configuring a Data Model's Style Sheet, you have global access to all Data Elements in the Data Model.

  • This means you can select any of them in a CSS rule.
  • Any style generically applied to a class (DataField for example), will be applied to all elements at any level in the Data Model's hierarchy.
  • You can style any specific Data Element by selecting it by name in the CSS rule.

LOCAL STYLING

(Data Sections & Data Tables)

When configuring a Data Section or Data Table's Style Sheet, you have local access to only its child Data Elements.

  • This means you can only select the child Data Elements in a CSS rule.
  • Any style generically applied to a class (DataField for example), will be applied only to child elements at the Data Section and Data Table's hierarchy.
    • Please note this means you cannot style the Data Section itself by editing its Style Sheet. You are only able to style children of the Data Section (or child HTML elements of the Data Section's HTML element).
  • You can style only specific children Data Elements by selecting them by name in the CSS rule.

Put another way, when you configure a Data Section or Data Table's Style Sheet, their name is prepended to the selectors you enter behind the scenes.

Question: Given a Data Section named "Header Details", what's the difference between the following two selectors?
  • Entered in the Data Model's Style Sheet: .Header_Details .DataField
  • Entered in the "Header Details" Data Section's Style Sheet: .DataField


Answer: Absolutely nothing!
  • The selectors would select the same HTML elements in both cases.
  • Behind the scenes, Grooper merges the CSS rule written to the "Header Details" Data Section with the main CSS file by prepending the section's class name to the selector.
    • So, the selector .DataField actually becomes .Header_Details .DataField when the Data Section's CSS is merged with the main CSS.

FYI [REVISED — verify against your version]

Some more recent Grooper versions support a special, non-standard self token inside a Style Sheet, which explicitly refers to "the element this Style Sheet is set on, plus everything inside it" without needing to hardcode that element's name. If self is available in your Grooper version, it can be a cleaner way of writing the kind of "prepended" scoping this section describes, and stays correct automatically if the element is ever renamed. Check your version's behavior in the Style Sheet editor's autocomplete before relying on it, since this is a newer addition not covered by the original testing behind this article.

So, why do one or the other? Let's look at the pros and cons.

GLOBAL STYLING

Pros

Cons

  • All CSS rules are managed in a single style sheet.
    • Only have to go to one place in the node tree to edit your CSS.
  • Easiest way to globally apply styling to all elements of a certain type.
  • Style sheets can be lengthy and disorganized.
    • Particularly if you have a large Data Model with several Data Sections and Data Tables, each one needing more specific custom styling rather than a general style applied to all of them.

LOCAL STYLING

Pros

Cons

  • Can be used as an organizational tool.
    • Buckets all CSS rules applied to children of a given Data Section, creating a series of smaller style sheets instead of one big one.
    • This can be particularly helpful for larger Data Models with several Data Sections and Data Tables, all needing more specific custom styling rather than a general style applied to all of them.
  • CSS rules are managed across multiple style sheets.
    • Must go to multiple places in the node tree to edit your CSS.
  • Can be confusing to keep track of which HTML elements are accessible.
    • Only children, not self (unless the self token described above is available and used deliberately).
  • Can be confusing if styling both the Data Model and Data Section/Data Table style sheets.
    • Data Section and Data Table style sheets will always "win out". If you're expecting a CSS rule from the Data Model's style sheet to be applied but the Data Section's CSS rule says something different, the Data Section's rule is always going to be applied.

Styling Flat Data Models VS Hierarchical Data Models

Generally speaking, there are two types of Data Models:

Flat Data Models

All Document Types share a single Data Model at the root of the Content Model.

  • Flat Data Models are intended to accommodate use cases where all Document Types share the same set of of data.
  • For example, you may have multiple Document Types for multiple vendors in an invoice processing model, but each Document Type's Data Model will collect the same set of information (invoice number, line item details, balance due, etc).

Hierarchical Data Models

Each Document Type executes its own unique Data Model formed by a hierarchy of inherited and children Data Elements.

  • Hierarchical Data Models are intended to accommodate situations where each Document Type has a unique or semi-unique set of data.
  • For example, a human resource document processing model may process a variety of documents (government forms like a W-4 form, internal forms, various benefits forms, etc).
    • Each may have their own unique set of information you want to collect (configured using the Document Type's Data Model) . But, they may share some information as well, such as an employee's name, date of birth or other identifying information (collected by a shared Data Model in the hierarchy, such as the Content Model's Data Model and merged with the fields in the Document Type's Data Model).

Thus far in this article, we've focused on flat Data Models to keep things simpler. Once you start working with more hierarchical models, you need to be careful about where you're editing the CSS. Each Data Model in the hierarchy has a Style Sheet property. Much like the Data Elements from each Data Model are ultimately merged to form a Document Type's Data Model the CSS rules from each style sheet is merged into a single one as well.


There may be some confusion when multiple Data Models attempt to style a specific property for an element using different values. You need to keep in mind two things:

  1. The most specific selector will always be applied.
    • If the Content Model's Data Model CSS has a more specific selector, its rule will be applied.
    • On the other hand, if the Document Type's Data Model CSS has a more specific selector, its rule will be applied.
  2. In cases where the specificity is ambiguous, the lowest level Data Model's style sheet will be applied.
    • In other words, A Document Type's Data Model is more specific than a Content Model's Data Model. Therefore, the Document Type's CSS rule would win out.

Creating and Using CSS Classes

Classes in CSS are a great way of tagging certain kinds of HTML elements for styling. For example, classes are how we distinguish between the HTML elements representing Data Fields and Data Sections. They're both div elements, but Data Fields are div elements with a DataField class where Data Sections have a DataSection class.

You can also create your custom CSS classes and assign them to any Data Element (Data Fields, Data Sections, Data Tables and Data Columns) using their CSS Class property.

  1. To create a CSS class, all you need to do is create a CSS rule in the Data Model's' Style Sheet.
    • Create the class by simply selecting its name like you would any other class, entering a period then the class name.
    • Here, we've added a class named example_class and styled it to give the HTML element an orange border. See below for the full CSS rule.
.example_class {
	border: 1px solid rgb(248,148,32);
	padding: 8px;
	border-radius: 4px;
}

There are the following naming restrictions for CSS classes.

  1. The letters must be alphanumeric, an underscore, or a hyphen (i.e. "a-z" "A-Z" "0-9" "_" or "-").
  2. The name cannot start with a digit.
  3. The name cannot start with two hyphens.
  4. The name cannot start with a hyphen followed by a number.
  5. Class names are case sensitive.


  1. To assign the class, select any Data Element in the Data Model.
    • Here, we've selected the "Employee Name" Data Field.
  2. In the CSS Class property, enter the name of the CSS class.
    • FYI: Multiple classes can be assigned by listing each one separated by a space.
      • i.e. class_name1 Class_name2 class_name3 etc.
  3. The style declarations in the CSS will be applied to the Data Element's HTML.


The class can be assigned to any Data Element you wish. Use classes to reuse CSS for multiple Data Elements in your Data Model.

Here, we've added the class to three Data Elements.

  1. The "Personal Info" Data Section
  2. The "Employee Name" Data Field
  3. The "Dependents" Data Table

Example style sheets

In this section, we will post various Data Model Style Sheet examples. Use them to get ideas for what you may be able to incorporate into your own Data Models.

Comments are included in some of these style sheets to document various CSS rules. See below for an example of a comment.

  • /*This is a comment*/

Editor's Note: Consider all the following CSS examples a "work in progress". These styles have not been extensively tested using real-world Content Models.

FYI [REVISED]

The examples below are preserved from the original article for their layout technique (block vs. inline-block manipulation, use of Data Sections to mirror a document's structure, etc.), which is still valid CSS regardless of Grooper version. Note that most color values in these examples are hardcoded rather than using the theme variables introduced earlier in this revision — that's a fine, valid choice, but if you're adapting one of these for your own use and want it to stay correct across dark/light mode, consider swapping literal colors for the var(--...) equivalents described in Using Theme Variables.

Generic Layout Examples

FYI

The Content Model and Data Model used to demonstrate these layouts can be found in the Grooper importable ZIP file found in the About section of this article.

List Layout

The List Layout styles fields as a simple list. This type of layout will often use margins and horizontal widths to better space out a list of fields and sections of fields. Left margins are often employed to indent Data Sections to make them more visually distinct from fields at the root of the Data Model and other sections of fields.

Below is an example of a generic List Layout style sheet.

CSS

"Info Sheet" Dummy Document Example

Sample Invoice Model Example

label {
  width: 140px;
}

.DataSection .DataField,
.DataSection .DataSection,
.DataTable table {
  margin-left: 32px;
}

.DataSection,
.DataTable,
.DataGridCollection {
  margin-top: 8px;
  margin-bottom: 8px;
}

Flow Layout

The Flow Layout stacks labels on top of their input boxes and lists them horizontally, wrapping fields to the next line when reaching the end of the screen (or containing HTML element). This layout can pack several fields into a relatively small space, conserving screen real estate. Label widths are typically less important to specify uses this layout. Instead Data Field horizontal margins and input widths are utilized to space out fields.

Below is a generic Flow Layout style sheet.

CSS

"Info Sheet" Dummy Document Example

Sample Invoice Model Example

.DataField {
	display: inline-flex;
	flex-direction: column;
}

.DataSection,
.DataTable,
.DataGridCollection {
	margin-top: 8px;
	margin-bottom: 8px;
}

Card Layout

The Card Layout relies heavily on Data Sections and borders to create distinct divisions between different kinds of fields on the document. Each section (or card) in the Card Layout will generally implore either a List Layout or Flow Layout within the boundaries of the card itself.

FYI [REVISED]

Before building a Card Layout by hand with the CSS below, check whether Grooper's built-in card CSS Class preset (see the note under Layout Styling above) already produces an acceptable result — it may save you from writing and maintaining this CSS yourself.

Below is a generic Card Layout style sheet.

  • This style sheet also uses the hover and focus-within pseudo-classes to lighten the borders around the card upon hovering your cursor and clicking inside the Data Section (focusing within it).
  • The focus-within pseudo-class was also used to add a drop shadow behind selected Data Sections and Data Tables.
    • More information on pseudo-classes can be found at w3Schools.
  • No background color was added to each card/section. However, that is often included in this style approach.
  • Because the fields in each card (i.e. the Data Fields in each Data Section) have a List Layout, you could call this a "List & Card Layout"
    • However, you could easily use a "Flow Layout" approach instead to create a "Flow & Card Layout". Simply remove the label rule and replace it with one that makes DataField elements some kind of inline element (such as the display: inline-flex; flex-direction: column declaration in the previous tab)

CSS

"Info Sheet" Dummy Document Example

Sample Invoice Model Example

label{
  width: 140px;
}

.DataSection,
.DataGridCollection,
.DataTable {
  border: 1px solid rgba(255,255,255,.25);
  padding: 16px;
  padding-top: 8px;
  border-radius: 4px;
  margin-top: 8px;
  margin-bottom: 8px;
  margin-right: 12px;
}

.DataGridCollection .DataSection {
  border: none;
  padding: 0px;
}

.DataSection:hover,
.DataTable:hover,
.DataGridCollection:hover {
  border-color: rgba(255,255,255,.5);
}

.DataSection:focus-within,
.DataTable:focus-within,
.DataGridCollection:focus-within {
  border-color: rgba(255,255,255,.75);
  box-shadow: 2px 2px 8px rgb(0,0,0,.5)
}

.DataGridCollection .DataSection:focus-within {
  box-shadow:none;
}

Simple Invoice Model Examples

These are a couple different Style Sheet examples for a PO-based invoice model.

Style 1 - Mixed Layout and New Caption Style

For a lot of document cases, you can't perfectly mirror a document's layout because you are processing a lot of different versions of the same kind of document.

Invoices are a good example of this. While you're always collecting (roughly) the same data from invoices (invoice number, invoice date, balance due, etc.), each different vendor is going to have a different format.

  • This Style Sheet attempts a "mixed layout" approach where the "Header Details" Data Section uses the "Flow Layout" and the "Amounts" Data Section uses a "List Layout".
  • This mixed approach styles the model to look at least more like an invoice than a flat list of fields.
  • This Style Sheet also styles the Data Section and Data Table captions differently (just for fun).

Full CSS

Data Model Preview

/*Generic Data Model styling*/

.DataSection {
  vertical-align: top;
  margin: 4px;
  height: 224px;
}

.DataField label {
  width: 120px;
}

.caption {
  text-align: center;
  border: solid rgba(255, 255, 255, .2);
  border-width: 1px 0px;
  margin-top: 16px;
  margin-bottom: 8px;
  padding: 4px 0px;
}

/*Header Details Data Section styling*/

.Header_Details {
  max-width: 416px;
  width: fit-content;	
}	
		
  .Header_Details .DataField {
    display: inline-flex;
    flex-direction: column;
  }

/*Amounts Data Section styling*/

.Amounts {
  max-width: 252px;
  text-align: right;
  margin-left: auto;
  margin-right: 24px;
}

  .Amounts .DataField label {
    margin-right: 8px;
  }

Style 2 - Inline-Block Data Sections and No Captions

This Style Sheet renders Data Sections as inline-block elements.

  • See the difference in the two Data Model preview images where the "Amounts" Data Section is moved to come before the "Line Items" Data Table'.
  • This Style Sheet also removes all Data Section and Data Table captions to give you a look at what that looks like.

Full CSS

Data Element Order

Data Model Preview

/*Generic Data Model styling*/

.DataField label {
  width: 120px;
}

.caption {
  display: none;
}
	
.DataSection {
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 5px;
  padding: 8px;
  display: inline-block;
  vertical-align: top;
  margin: 4px;
  max-height: 216px;
}

/*Header Details Data Section Styling*/

.Header_Details {
  max-width: 420px;
  width: fit-content;
}

  .Header_Details .DataField {
    display: inline-flex;
    flex-direction: column;
}

Another Mirrored Layout Example

This is another example of a "mirrored layout" styled Data Model. It aims to more closely mirror the layout of the Application For Cow Ownership document, which is a much more data dense document than our example in the Layout Styling section of this article.

/*Establishes "highlight" CSS class*/

.highlight input {
	color: Yellow;
	font-weight: bold;
}

.highlight label {
	color: DeepSkyBlue;
}

/*Establishes the "blur" CSS class*/

.blur:not(:focus-within) > *:not(.caption) {
  filter: blur(4px);
}

/*Establishes basic styling for Data Sections and Data Tables*/

.DataSection, 
.DataTable,
.DataGridCollection {
	max-width: 876px;
	border: 1px solid rgba(255,255,255,0.25);
	border-radius: 5px;
	margin-top: 8px;
	margin-bottom: 8px;
	padding: 16px;
	padding-top: 8px;
}
	
	/*Colors borders around Data Sections and Data Tables when hovering your cursor over
	them (soft white) and entering fields (bright white).*/

	.DataSection:hover, 
	.DataTable:hover, 
	.DataGridCollection:hover {
		border-color: rgba(255,255,255,.5);
	}
	
	.DataSection:focus-within, 
	.DataTable:focus-within, 
	.DataGridCollection:focus-within {
		border-color: rgba(255,255,255,.75);
  	    box-shadow: 1px 1px 12px rgb(0,0,0,.5), -1px 0px 8px rgb(0,0,0.5);
	}

	.DataGridCollection .DataSection:focus-within {
		box-shadow: none;
	}
	
/*Purely aesthetic rule to extend the background of a Data Table to the width of the
widest Data Section*/

.DataTable {
	width: auto;
}
	
/*Establishes styling ONLY for Data Fields at the first level of the Data Model's 
hierarchy (That is to say any Data Field NOT in a Data Section).*/

.DataModel > .DataField {
	display: inline-block;
	margin-right: 32px;
	margin-top: 16px;
}

/*Aligns Data Field labels vertically on top of their input boxes for any Data Field in
a Data Section and the "Comments" Data Field.*/

.DataSection .DataField, 
.Comments {
	display: inline-flex;
	flex-direction: column;
}

/*Styles the Education section and its elements. Mostly, syling is done to produce two 
inline Data Tables inline beside the single Data Field in the section.*/

/*.Education {
	white-space: nowrap;
}*/

.Education .DataTable {
	display: inline-table;
	padding-left: 0px;
	padding-right: 0px;
	background-color: rgba(255,255,255,0.05);
}

.Education .DataTable .caption {
	text-align: center;
}
	
.Education .DataField {
  text-align: center;
  margin-top: 16px;
}

/*Styles Data Fields in the Signatures Data Section*/

.Signatures .DataField {
	display: grid;
  grid-template-columns: 250px auto;
}

.Signatures .Approval_Signature, 
.Signatures .Signature_Date {
  display: inline-grid;
}

Example CSS classes

Highlight Class

This class was designed to quickly highlight certain fields.

  • It turns a Data Field's label blue and its input text bold yellow. But you can pick whatever colors you want.
  • This could be used to bring critical fields to a user's attention in Review.

See the CSS for the rule below:

.highlight label {
	color: DeepSkyBlue;
	font-weight: bold;
}
.highlight input {
	color: Yellow;
	font-weight: bold;
}

Note we needed two CSS rules to accomplish this, both declaring the highlight class. The first styles child label HTML for any Data Element using the highlight class. The second styles child input HTML.

FYI [REVISED]

As written, this rule only reaches fields that render as an input — Regular, Read Only, and Placeholder Text fields. If you want this same highlight to also work on multiline, list, or pick-list fields, replace input with .DataValue in the second rule, since .DataValue is present on every field's value element regardless of its underlying tag:

.highlight .DataValue {
	color: Yellow;
	font-weight: bold;
}

Blur Class

This CSS class blurs Data Sections/Data Tables that are not currently being edited.

  • This could be used to protect PII or other sensitive data, only keeping it visible on the screen while the user is actively editing the sensitive data.
  • This could also be used to protect against eye strain. There's less noise for the user to focus on if only what they're actively editing is literally in focus.

The following CSS class would be added to your Data Model's Style Sheet text.

.blur:not(:focus-within) > *:not(.caption) {
  filter: blur(4px);
}

In the image here, we've added the blur class to each Data Section and Data Table in the Data Model.

FYI

This CSS rule uses the focus-within pseudo-class.

  • More information on pseudo-classes can be found at W3Schools.

Auto display lines class

Multiline field without AutoHeight class

Multiline field with AutoHeight class

This CSS class changes how multiline Data Fields/Data Columns behave.

By default, multiline Data Fields are enabled by enabling the "Multi Line" property and setting a number of "Display Lines". If the number of lines exceeds this number a slider appears to scroll through the lines. This makes things difficult for a user to quickly review fields that exceed the number of display lines.

This "AutoHeight" class automatically adjusts the number of display lines, expanding to fit the content.

  • Be aware: To apply this behavior to Data Columns, add this class to the Data Table not the multiline Data Column.
.AutoHeight > .DataValue {
  min-height: 24px;
  height: 100% !important;
  max-height: fit-content !important;
  overflow-y: visible;
}

.AutoHeight > .scroll-container > div > table div {
  min-height: 24px;
  height: 100% !important;
  max-height: fit-content !important;
  overflow-y: visible;
}

.AutoHeight > .scroll-container > div > table tbody tr td select {
  height: 100%;
}

Bonus: Auto row height

The AutoHeight class as written above will only adjust the height of the multiline cell, not the entire row of an extracted Data Table.

Add this CSS rule to the AutoHeight class to adjust the entire row's height too.

.AutoHeight .cell {
  height: 100%;
}

FYI [REVISED]

As noted in the new Tabular View section above, a multi-instance Data Section's body cells drop the .cell class while switched to Tabular View. This "Bonus: Auto row height" rule will therefore have no effect on rows in Tabular View — only on a genuine Data Table's rows, or a Standard View multi-instance section's cells if those happen to carry .cell in your version. If you need consistent row-height behavior in both view modes, you'd need to add a parallel rule targeting the Tabular View's row structure as well.

Using the Included Style Sheets property

Data Element containers (Data Models, Data Sections and Data Tables) all have an "Included Style Sheets" property. This allows users to reference CSS files brought into a Project as a Resource File.

Use "Included Style Sheets" to:

  • Reference a single style sheet across multiple Data Models.
  • Standardize Data Grid styling across multiple Grooper Repositories.
  • Store and manage bulk style rules outside of Data Model/Data Section/Data Table nodes.
  • Share CSS with other Grooper designers.


To configure "Included Style Sheets":

  1. Drag a CSS file from your computer to the Project (or a folder in the Project).
  2. This creates a "Resource File" Grooper can reference.
  3. Navigate to the Data Model (or Data Section or Data Table) you wish to style.
  4. Open the "Included Style Sheets" editor.
  5. This opens a reference editor. Find the Resource File and check the box next to it to reference it.
  6. Press "OK" when finished to close the editor.
  7. Save changes to the Data Model (or Data Section or Data Table).

Summary of Revisions in This Pass [REVISED — NEW SECTION]

For editors comparing this version against the original three-year-old article, here's what changed:

  • Added: a full Field States section covering read-only fields (attribute vs. class gotcha), required/invalid state, and the two custom list elements (combo-box, multi-choice) with their confirmed non-shadow-DOM behavior.
  • Added: a Tabular View section documenting the VirtualTable structure multi-instance Data Sections switch to.
  • Added: a Using Theme Variables subsection under Color Styling, plus inline callouts pointing existing hardcoded-color examples toward the new variables.
  • Corrected: the "Data Field = 3 elements" framing at the top of CSS Basics now calls out the other four possible tags a Data Field's value can render as.
  • Flagged for re-verification (not corrected, since it couldn't be confirmed during this pass): the exact tag breakdown for .caption across single-instance sections, multi-instance sections, and Data Tables.
  • Noted but not restructured: the "Mirrored Layout" worked examples in the Layout Styling section remain as originally written; they are pedagogically solid and not factually wrong, just lengthy. A future pass could consolidate the repeated "block vs inline-block" explanation across the multiple worked examples into a single reference table, similar to how the "Example style sheets" section already uses collapsible tabs.
  • Untouched: CSS basics, combinators, box model, margins/borders/padding, and the worked layout examples — all still technically accurate CSS regardless of Grooper version.