Skip to main content

Styling Ballot Errors and Warnings with Custom CSS

While a voter fills in their ballot, the Voting Portal validates the selections and displays error and warning boxes — for example when the voter selects fewer choices than the minimum, exceeds the maximum, or leaves a preferential order with gaps. Each of these boxes carries stable CSS hooks so that individual messages can be styled (or hidden) using the Custom CSS setting, without affecting the rest of the messages.

Custom CSS can be configured in the Admin Portal under Data → Ballot Design → Custom CSS, at the Election Event level or per Election.


CSS hooks

Every error or warning box rendered by the Voting Portal exposes:

  • A message-specific CSS class, derived from the message identifier by prefixing warn-- and replacing every character that is not a letter, digit, underscore or hyphen with a hyphen. For example, the message errors.implicit.underVote gets the class warn--errors-implicit-underVote.
  • data-warn-id: the raw message identifier, e.g. data-warn-id="errors.implicit.underVote".
  • data-warn-type: the category of the validation, one of Implicit, Explicit or EncodingError (see Message types below).

Messages are shown in two severities:

  • Errors are shown in warning boxes (yellow by default). They indicate the selection is invalid or could not be decoded.
  • Alerts are shown in info boxes (blue by default). They inform the voter about something noteworthy — such as an undervote — that does not necessarily invalidate the ballot.

Errors also appear on the review screen next to each contest before the ballot is cast, with the same CSS hooks.

Message types

The data-warn-type attribute classifies each message:

  • Implicit: the combination of selections makes the vote invalid or noteworthy (undervote, overvote, blank vote, duplicated preference position, …). Whether each condition produces an error, an alert, or nothing depends on the corresponding contest policy (invalid vote policy, over/under vote policy, etc.).
  • Explicit: related to the voter explicitly marking the ballot as invalid, where the contest configuration allows or disallows it.
  • EncodingError: the ballot could not be correctly encoded or decoded (for example, a write-in text that is too long).

Message reference

Message identifierCSS classTypeSeverity
errors.implicit.selectedMinwarn--errors-implicit-selectedMinImplicitError. Fewer choices selected than the minimum.
errors.implicit.selectedMaxwarn--errors-implicit-selectedMaxImplicitError (overvote); depending on the over vote policy it is also raised as an alert.
errors.implicit.underVotewarn--errors-implicit-underVoteImplicitAlert. Fewer choices selected than the maximum (shown when the under vote policy is not ALLOWED).
errors.implicit.overVoteDisabledwarn--errors-implicit-overVoteDisabledImplicitAlert. The maximum number of selections was reached and further options are disabled.
errors.implicit.blankVotewarn--errors-implicit-blankVoteImplicitError when the blank vote policy is NOT_ALLOWED, alert otherwise.
errors.implicit.maxSelectionsPerTypewarn--errors-implicit-maxSelectionsPerTypeImplicitError. More choices selected for a candidate list than that list's maximum.
errors.implicit.duplicatedPositionwarn--errors-implicit-duplicatedPositionImplicitError. The same preference position was selected for two or more candidates.
errors.implicit.preferenceOrderWithGapswarn--errors-implicit-preferenceOrderWithGapsImplicitError. The order of preference has one or more gaps.
errors.explicit.notAllowedwarn--errors-explicit-notAllowedExplicitError. The ballot was explicitly marked invalid but the contest does not allow it.
errors.explicit.alertwarn--errors-explicit-alertExplicitAlert. The selection marked will be considered an invalid vote.
errors.encoding.writeInCharsExceededwarn--errors-encoding-writeInCharsExceededEncodingErrorError. Write-in text exceeds the maximum number of characters.
errors.encoding.notEnoughChoiceswarn--errors-encoding-notEnoughChoicesEncodingErrorError. Not enough choices to decode the ballot.
errors.encoding.writeInChoiceOutOfRangewarn--errors-encoding-writeInChoiceOutOfRangeEncodingErrorError. A write-in choice is out of range.
errors.encoding.writeInNotEndInZerowarn--errors-encoding-writeInNotEndInZeroEncodingErrorError. A write-in encoding doesn't end in 0.
errors.encoding.bytesToUtf8Conversionwarn--errors-encoding-bytesToUtf8ConversionEncodingErrorError. A write-in could not be converted from bytes to a UTF-8 string.
errors.encoding.ballotTooLargewarn--errors-encoding-ballotTooLargeEncodingErrorError. The encoded ballot is larger than expected.
errors.encoding.invalidMaxVoteswarn--errors-encoding-invalidMaxVotesEncodingErrorError. The contest's maximum votes configuration is invalid.
errors.encoding.invalidMinVoteswarn--errors-encoding-invalidMinVotesEncodingErrorError. The contest's minimum votes configuration is invalid.

Examples

Highlight the undervote alert with a red border and bold text:

.warn--errors-implicit-underVote {
border: 2px solid #d32f2f;
font-weight: bold;
}

Hide the "maximum reached" alert entirely:

.warn--errors-implicit-overVoteDisabled {
display: none;
}

Style a whole category of messages using the data-warn-type attribute:

[data-warn-type="EncodingError"] {
background-color: #fdecea;
}

Target a message by its raw identifier instead of the derived class:

[data-warn-id="errors.implicit.selectedMax"] {
text-decoration: underline;
}

Since the Custom CSS setting exists both on the Election Event and on each Election, styles can be applied globally to the whole event or only to a specific election.