14
Using CSS
Arnold Smith edited this page 2024-10-05 15:30:23 +02:00

Introduction to CSS

Click to see tutorial on CSS

Click to see tutorial on changing cursors with CSS

The css widget property can be set to a string, a simple object, or a compound object. Using a string or a simple object are functionally equivalent, while compound objects provide more functionality. For more information on the structure of css itself, see here. That site also provides links to more detailed css documentation.

If css is a string or a simple object, its contents will be applied to the style attribute of the widget as inline css. Note that some widgets have css-specific properties (for example, width, height, rotation, scale, borderRadius as well as others); css properties corresponding to these additional widget properties are added to the widget's inline styles by the game engine.

CSS as String

Example css as a string:

"css":"border-image-source: url(/assets/-1113368112_84025) !important; border-image-slice: 50 !important; border-image-width: 25px !important; border-image-outset: 23px !important; border-image-repeat: round !important; background: transparent; filter: drop-shadow(-1px 2px 7px #000)"

CSS as Simple Object

If css is a simple object, the object keys are simply used as the css property names and the css string is generated from the object. This can make the json easier to read, but provides the same functionality as the simple string value. The above example could be wrtten as:

"css": {
  "border-image-source":"url(/assets/-1113368112_84025) !important",
  "border-image-slice": "50 !important",
  "border-image-width": "25px !important",
  "border-image-outset": "23px !important",
  "border-image-repeat": "round !important",
  "background": "transparent",
  "filter": "drop-shadow(-1px 2px 7px #000)"
}

CSS as Compound Object

If css is a compound object, a style sheet for the widget is generated by using the outer keys to create selectors and the nested object to create the style rules. Special keys default and inline are provided. default creates an ID selector for the widget. inline places the defined style rules in the element's style attributes instead of the style sheet. Basic class selector keys of dragging and draggingSelf are also available. dragging is active when the widget starts movement (but not just clicking) by a player's action. draggingSelf is the same except that the style rules will only be effective for the player doing the dragging. Any other value is appended after the widget id so rules like #widgetID:hover or #widgetID::after can be created. The below example moves the styles to a stylesheet and adds a yellow background glow on hover to the above example.

"css": {
  "default": {
    "border-image-source":"url(/assets/-1113368112_84025) !important",
    "border-image-slice": "50 !important",
    "border-image-width": "25px !important",
    "border-image-outset": "23px !important",
    "border-image-repeat": "round !important",
    "background": "transparent",
    "background-color": "green",
    "filter": "drop-shadow(-1px 2px 7px #000)"
  },
  ":hover": {
    "background-color": "rgba(255, 255, 63, .25)"
   }

Dynamic Values and Variables

Values of css properties can use properties from the widget itself using syntax similar to the dynamic expressions found in routines. Only properties of the current widget are supported: ${PROPERTY propertyName} works, but ${PROPERTY propertyName OF widgetID} does not. There are no variables to use so ${variableName} does not work either.

  "css": {
    "default": {
      "background-size": "75%",
      "font-weight": "bold",
      "font-size": "140%",
      "color": "red",
      "box-shadow": "0px 0px 20px 5px ${PROPERTY customColor}"
    },
    ":hover": {
      "color": "${PROPERTY customColor}"
    }
  }

Property replacement only works in the widget's css property, not properties that apply styles directly to sub-elements of the widget (such as spinnerCSS, valueCSS, handleCSS, and css on card faces). To use on a sub-element, you can either write a stylesheet css property with selectors to match the sub element or use the widget css to create a css variable from the property.

  "css": {
    ">.value": {
      "cssProperty": "${PROPERTY widgetPropertyName}"
    }
  }
  "css": "--cssVariableName: ${PROPERTY widgetPropertyName}",
  "valueCSS": "cssProperty: var(--cssVariableName)"

Note that child widgets can also be targeted by starting the selector with a space according to css selector rules; however, a planned change to the DOM structure of widgets and their children may mean that selectors using this feature may need to be changed in the near future.

VTT Specific CSS Variables

Also note that some widgets use css variables that are system-defined (for example, Buttons can use --wcMain or --wcMainOH to control the button color and the on-hover color (Click to see tutorial), or dice as described below). While these css variables can still be used and modified, in general the functionality provided by the compound object form allow for a more intuitive and more general way to represent these ideas.

Dice

Click to see tutorial

Like some other widgets, dice have their own set of css values that can be changed. The easiest way is using the "faceCSS" property. It works as a property on the dice for all faces or as an individual parameter on specific faces.

For example, to change the font size for all faces, place the following as a property on the dice:

"faceCSS": {
   "font-size": "25px"
 }

Or to set a different font size on each face, put the "faceCSS" as a parameter in the "faces" object like this:

 "faces": [
    {
      "text": "Hello",
      "faceCSS": {
        "font-size": "25px"
      }
    },
    {
      "text": "Hi",
      "faceCSS": {
        "font-size": "30px"
      }
    }
 ]

A few dice specific css variables are also available to further tweak the appearance, including: --faceBorder, --borderColor, --pipColor, and --edgeColor, which are explained at Dice.

animatePropertyChange

animatePropertyChange can be applied to any widget type. It can be used to set or change css properties for designated periods of time. It sets a class on a widget temporarily when a delta contains the property. The default class name is animate_ followed by the property name escaped with the same method used for widget DOM ids ([0-9A-Za-z] not changed, underscore doubled, other characters escaped as hex codes formatted like x####). The property can use string form to state the property that will be changed (using a default time of 1000ms), or it can be in object form. Consider the following JSON on a button:

"animatePropertyChange": [
   {
      "property": "clickCount",
      "className": "clickCount"
    },
    {
      "property": "clickCount",
      "duration": 5000
    }
  ],
  "css": {
    ".animate_clickCount": {
      "background-color": "red"
    }
  },
  "clickRoutine": [
    {
      "func": "SET",
      "collection": "thisButton",
      "property": "clickCount",
      "relation": "+",
      "value": 1
    }
  ]

Each time the button is clicked, the property of clickCount is changed. That change triggers the animatePropertyChange action and the color of the button switches to red for 3000ms. To use the simpler form and accept the 1000ms default, you could use:

"animatePropertyChange": ["clickCount"],

All clients that were connected when the change occurred will see the change, but newly connected clients will not, even if the duration of the change is long enough that other clients are still showing it. If late joining clients should still see the change, a timer widget should be used instead.