Lesson 38 of 45 · Web pages

The rest of CSS

The earlier lessons covered text, boxes, color and layout. This one finishes the list: the properties for numbered lists and counters, for tables, for scrolling that snaps into place, for tooltips tied to an anchor, and for drawing with SVG. Every one has a short example, and the reference at the end lists all 94 with what they accept.

Lists and their markers

Every item of a list has a marker: the bullet of a list or the number of an ordered list. The browser draws it, and you choose how with three properties. list style type sets the look. It takes a keyword such as disc, square, decimal, lower-roman or upper-alpha, none for no marker, or a text of your own. A text must keep its quotes in the CSS, so in Salam write it between backticks: list style type = `"» "`. list style position says whether the marker hangs outside the text (outside, the default) or sits inside the first line (inside). list style image uses a picture or a gradient instead of a character.

list style is the shorthand for all three, written as one string such as "square outside". Look at the last two lists in the preview: with a marker outside, every line of a long item starts at the same edge, and with a marker inside the second line wraps under the marker.

web-more-lists.salam
page:
    title = "List markers"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    heading: size = 3 content = "Roman numerals" end
    ordered list: list style type = lower-roman
        item: content = "Preface" end
        item: content = "Chapters" end
        item: content = "Index" end
    end
    heading: size = 3 content = "Your own marker" end
    list: list style type = `"» "`
        item: content = "Open the box" end
        item: content = "Read the label" end
    end
    heading: size = 3 content = "Inside and outside" end
    list: list style position = inside background = "#ccfbf1" max width = "20rem" padding = 8
        item: content = "The marker sits inside the text, so a second line starts under it." end
    end
    list: list style = "square outside" background = "#e2e8f0" max width = "20rem" padding = 8 padding inline start = 32
        item: content = "The marker hangs outside, so every line starts at the same edge." end
    end
    list: list style image = "linear-gradient(#0f766e, #38bdf8)"
        item: content = "An image as the marker" end
    end
end

These properties style the marker as a whole. You cannot give one marker a color of its own with them. The marker takes the color and the font of its item, so to change it, change the item.

Counters: numbering with CSS

A counter is a number that the browser keeps under a name. Three properties work with it. counter reset creates it on an element, or sets it back to a start value: "chapter" starts at 0 and "chapter 4" at 4. counter increment adds to it each time an element that has the property is drawn, by 1 or by the number you give. counter set puts a value into it without adding. When both increment and set sit on one element, the set wins.

A counter is invisible until you print it. For that, write counter(chapter) in the generated content of a before or after rule, which adds text in front of or behind an element. A text next to it goes in quotes inside the string: "counter(chapter) \". \"". If you reset a lesson counter on every chapter heading, it starts again in each chapter and gives 1.1, 1.2, 2.1. The example does exactly that: every chapter heading resets the lesson counter and every lesson paragraph increments it.

web-more-counters.salam
page:
    title = "Numbered outline"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    box: counter reset = chapter
        heading:
            size = 3
            counter increment = chapter
            counter reset = lesson
            before generated content = "counter(chapter) \". \""
            content = "Getting started"
        end
        paragraph: counter increment = lesson before generated content = "counter(chapter) \".\" counter(lesson) \"  \"" content = "Install the compiler" end
        paragraph: counter increment = lesson before generated content = "counter(chapter) \".\" counter(lesson) \"  \"" content = "Your first page" end
        heading:
            size = 3
            counter increment = chapter
            counter reset = lesson
            before generated content = "counter(chapter) \". \""
            content = "Styling"
        end
        paragraph: counter increment = lesson before generated content = "counter(chapter) \".\" counter(lesson) \"  \"" content = "Colors and fonts" end
        heading:
            size = 3
            counter set = "chapter 9"
            counter reset = lesson
            before generated content = "counter(chapter) \". \""
            content = "Appendix"
        end
        paragraph: counter increment = lesson before generated content = "counter(chapter) \".\" counter(lesson) \"  \"" content = "Glossary" end
    end
end

The appendix heading uses counter set = "chapter 9": it jumps to 9 and its lessons follow as 9.1. The counter() function takes a second value, a list style, and the Persian version of the example uses it as counter(chapter, persian) to print Persian digits. For nested numbers such as 1.2.3 in one go, counters(name, ".") joins every level of the counter with a separator.

The before and after prefixes work on elements and components, but not inside a global rule, where they are silently dropped. If the numbering does not appear, check where the rule is written. Also note that two elements with the same styles share one CSS class, while two with different styles that you named with the same class are a compile error, so name a class only on elements that really look alike.

Quotation marks

The quote element puts quotation marks around its text, and which marks it uses comes from the quotes property. The value is pairs of strings: the first pair is the outer level, the second pair is for a quote inside a quote, and so on. Quote marks in the value need backticks again. The first two paragraphs of the example show the same nested sentence with two sets of marks. quotes = "none" removes the marks, and for a block quote, which has none of its own, you can add them with the keywords open-quote and close-quote in generated content, as in the last line of the example. Those keywords use the same quotes pairs, so the marks stay consistent.

web-more-quotes.salam
page:
    title = "Quotation marks"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    paragraph: quotes = `"“" "”" "‘" "’"`
        content = "Sara said, "
        quote: content = "Omid told me "
            quote: content = "never stop" end
        end
        span: content = "." end
    end
    paragraph: quotes = `"«" "»" "‹" "›"`
        content = "The same sentence with other marks: "
        quote: content = "Omid told me "
            quote: content = "never stop" end
        end
    end
    block quote: quotes = "none" border = "none" margin = "1rem 0" color = "#475569"
        content = "Quote marks off."
    end
    block quote: quotes = `"[" "]"` color = "#0f766e"
        before generated content = open-quote
        after generated content = close-quote
        content = "Added with open-quote and close-quote."
    end
end

Table borders and layout

A table has two models for its borders. With border collapse = separate (the default) every cell keeps a complete border of its own and the gaps between cells are set with border spacing: one length for both directions, or two for horizontal and vertical. With collapse neighbouring borders merge into a single line and border spacing does nothing. empty cells = hide leaves out the border and background of a cell with no content, but only in the separate model. caption side moves the caption to the bottom. The first table below shows the separate model with its hidden empty cell, and the second shows collapsed borders.

web-more-table.salam
page:
    title = "Table settings"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    global: selector = "td, th" border = "2px solid #0f766e" padding = "6 14" end
    table: border collapse = separate border spacing = "10 4" empty cells = hide caption side = bottom margin = "0 0 1.5rem"
        caption: content = "Separate borders, empty cells hidden" end
        header:
            row:
                column: content = "Item" end
                column: content = "Note" end
            end
        end
        row:
            cell: content = "Tea" end
            cell: end
        end
    end
    table: border collapse = collapse table layout = fixed width = "22rem"
        caption: content = "Collapsed borders, fixed layout" end
        header:
            row:
                column: content = "Item" end
                column: content = "A long heading in a column of fixed width" end
            end
        end
    end
end

The second table uses table layout = fixed. With the default auto layout the browser measures every cell before it decides on column widths, so one long cell can stretch its column and the table can end up wider than you asked. A fixed layout reads only the table width and the first row and divides the space, so the columns stay put and long text wraps inside them. It also draws a big table faster. It needs a width on the table to have any effect.

Scrolling that snaps

Scroll snapping makes a scrolling box come to rest on chosen points instead of anywhere, like the pages of a gallery. It takes two sides. On the scroll container, scroll snap type turns it on: an axis (x, y or both) and a strictness. mandatory always comes to rest on a point, proximity only when the scroll stops near one. On each child, scroll snap align says which edge of the child lines up with the container: start, center or end. scroll snap stop = "always" adds that a fast flick may not skip past the child, which is what you want for a slide show.

The example below is a strip of four slides. The container has overflow x = auto to scroll and scroll snap type = "x mandatory". The slides are styled with one global rule using the selector #strip > *, which is shorter than repeating the same line on four boxes. Scroll the strip with your finger, a mouse wheel or the keys and watch it settle on a slide.

web-more-snap.salam
page:
    title = "Snapping slides"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    global: selector = "#strip > *" flex = "0 0 80%" height = 120 color = white font size = "1.6rem" display = flex align items = center justify content = center border radius = 12 scroll snap align = start scroll snap stop = always end
    style: content = "#strip::scroll-marker-group { display: flex; gap: 8px; justify-content: center; padding: 8px } #strip > *::scroll-marker { content: ''; width: 10px; height: 10px; border-radius: 50%; background: #94a3b8 } #strip > *::scroll-marker:target-current { background: #0f766e }" end
    box: id = "strip" display = flex gap = 12 overflow x = auto padding = "0 20" scroll snap type = "x mandatory" scroll padding = "0 20" scroll marker group = after
        box: background = "#0f766e" content = "One" end
        box: background = "#2563eb" content = "Two" end
        box: background = "#c2410c" content = "Three" end
        box: background = "#7c3aed" content = "Four" end
    end
    paragraph: content = "Scroll the strip sideways. It always stops with a slide at the edge." end
end

Two more properties adjust where "start" is. scroll padding goes on the container and shrinks the area that counts: "0 20" keeps a slide 20 pixels away from the left and right edges, so that the next slide peeks in, and it stops a fixed header from covering a heading that the page jumps to. scroll margin goes on the child and grows its snap area on its own. Both come in sides: top, right, bottom and left, and the logical ones, block and inline with start and end, which turn around in a right to left page. Use the logical ones for anything that scrolls sideways, because in a Persian page the first slide is at the right.

The little dots in the preview are made by the browser, not by elements. scroll marker group = "after" asks for a row of markers after the container, one for each child, and the raw style element styles them with ::scroll-marker and ::scroll-marker-group, which the page language has no names for. The dot of the slide in view also matches :target-current, so it can have its own color, and clicking a dot scrolls to its slide. scroll target group = "auto" does the same job for a list of links, such as a table of contents that highlights the section you are reading. Both exist today in Chromium browsers only, so keep the page usable without them.

Snapping only helps readers who scroll. Do not use it to hide content: keep everything within reach of a plain scroll, and try the page with the keyboard too, which moves the container in the same way.

Anchor positioning

A tooltip, a menu or a popup belongs next to the thing it explains. For years that needed JavaScript that measured the page. Anchor positioning does it in CSS. You give an element a name with anchor name, which must start with two hyphens, like "--target". Another element that is position = absolute chooses that name with position anchor and says where to sit with position area. The area is a cell of a three by three grid around the anchor: top, bottom, left, right, center, corners such as top right, and stretched cells like top span-right.

The example has four buttons. Each one runs a small function when it is clicked, and the function sets the position-area of the tooltip with dom.SetStyle. The tooltip jumps around the anchor and no coordinates are calculated anywhere. The functions of dom are described on the dom page.

web-more-anchor.salam
import dom

page:
    title = "Anchored tooltip"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    box: display = flex gap = 8 margin = "0 0 1rem"
        button: click = (): dom.SetStyle(dom.ById("tip"), "position-area", "top") end content = "Top" end
        button: click = (): dom.SetStyle(dom.ById("tip"), "position-area", "right") end content = "Right" end
        button: click = (): dom.SetStyle(dom.ById("tip"), "position-area", "bottom") end content = "Bottom" end
        button: click = (): dom.SetStyle(dom.ById("tip"), "position-area", "left") end content = "Left" end
    end
    box: position = relative height = 220 border = "1px dashed #94a3b8" border radius = 8
        box: id = "target" anchor name = "--target" margin = "80 auto 0" width = 120 padding = 12 text align = center background = "#0f766e" color = white border radius = 6 content = "Anchor" end
        box: id = "tip" position = absolute position anchor = "--target" position area = top position try fallbacks = flip-block position visibility = anchors-visible margin = 6 padding = "4 10" background = "#0f172a" color = white border radius = 6 content = "Tooltip" end
    end
end

Two more properties make the tooltip behave near the edge of the screen. position try fallbacks = "flip-block" lists other places to try when the first one would run off screen: flip-block mirrors it to the other side, flip-inline does so sideways. position visibility = "anchors-visible" hides the tooltip when its anchor has scrolled out of view, so that it does not float alone. position try order and the shorthand position try rank the fallbacks by the room they leave. Finally anchor scope keeps names local to a part of the page, so that a component used ten times can use the same name in each copy without mixing them up.

Anchor positioning is new. Chromium browsers have it and the others are catching up, and a browser that lacks it ignores these lines, so the tooltip stays where it would be without them. Test it in the browsers your readers use, and have a plain fallback such as showing the text below the button.

SVG presentation properties

The svg element holds a drawing. Its content is raw SVG markup that the compiler passes on unchanged, so shapes such as <circle> and <path> are written as text. What the page language adds is the styling. The properties of this section are SVG presentation properties, and they reach the shapes in two ways.

The first way is inheritance. fill, stroke, stroke width, paint order, text anchor and the marker properties are inherited, so one line on the svg element styles every shape inside. fill is the color inside a shape and stroke is the line along its edge; with no stroke only the fill shows. The first example puts them on three drawings. fill rule = "evenodd" leaves a hole in the star where its lines cross. stroke dasharray alternates dash and gap, stroke dashoffset shifts the pattern, and a round stroke linecap turns the dashes into dots. stroke linejoin shapes a corner, and stroke miterlimit cuts a sharp point flat when it would stick out too far.

web-more-svg-stroke.salam
page:
    title = "Fill and stroke"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    box: display = flex gap = 24 flex wrap = wrap
        box:
            svg: view box = "0 0 100 100" width = 120 height = 120 fill = "#5eead4" fill opacity = 0.6 fill rule = evenodd stroke = "#0f766e" stroke width = 3 stroke linejoin = round
                content = "<polygon points='50,5 80,95 5,35 95,35 20,95'/>"
            end
            paragraph: content = "Even-odd fill" end
        end
        box:
            svg: view box = "0 0 100 100" width = 120 height = 120 fill = none stroke = "#c2410c" stroke width = 8 stroke linecap = round stroke dasharray = "1 14" stroke dashoffset = 4
                content = "<circle cx='50' cy='50' r='38'/>"
            end
            paragraph: content = "Dotted line" end
        end
        box:
            svg: view box = "0 0 100 100" width = 120 height = 120 fill = none stroke = "#2563eb" stroke width = 14 stroke linejoin = miter stroke miterlimit = 2
                content = "<polyline points='15,85 50,15 85,85'/>"
            end
            paragraph: content = "Sharp corner, cut by the limit" end
        end
    end
end

Text in SVG has its own rules. text anchor decides which part of the text sits on its x point: middle centres it. paint order = "stroke fill" draws the outline first, so the fill covers its inner half and outlined letters stay thick. dominant baseline and baseline shift change the line that letters rest on, and they are not inherited, so they go on one text only. That is the second way to reach a shape: a global rule with a selector such as "#b". The page language does not name the shapes inside the raw markup, but CSS can still find them by id, class or tag.

web-more-svg-text.salam
page:
    title = "Text in SVG"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    global: selector = "#a" dominant baseline = hanging end
    global: selector = "#b" dominant baseline = middle end
    global: selector = "#sup" baseline shift = super font size = 14 end
    svg: view box = "0 0 360 140" width = 360 height = 140 font size = 20 font weight = bold fill = "#fde68a" stroke = "#0f172a" stroke width = 4 paint order = "stroke fill" text anchor = middle
        content = "<line x1='0' y1='45' x2='360' y2='45' stroke='#ef4444' stroke-width='1'/><text id='a' x='60' y='45'>hanging</text><text id='b' x='180' y='45'>middle</text><text x='300' y='45'>alphabetic</text><text x='180' y='110'>E = mc<tspan id='sup'>2</tspan></text>"
    end
end

The same way works for the properties that only a shape has. cx, cy and r place and size a circle, rx and ry do it for an ellipse or round the corners of a rectangle, x and y move a rectangle, and d holds the outline of a path. They are attributes in old SVG and CSS properties in modern browsers, which is what lets a hover rule grow the circle below and a transition animate it.

web-more-svg-geometry.salam
page:
    title = "Geometry from CSS"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    global: selector = "#c" cx = 60 cy = 60 r = 30 transition = "r 0.2s" end
    global: selector = "#c:hover" r = 48 end
    global: selector = "#e" cx = 170 cy = 60 rx = 40 ry = 22 end
    global: selector = "#r" x = 230 y = 30 rx = 14 ry = 14 end
    global: selector = "#p" d = "path('M 10 135 C 70 112 130 112 190 135 L 290 135')" end
    svg: view box = "0 0 300 140" width = 300 height = 140 stroke = "#0f172a" stroke width = 2
        content = "<circle id='c' fill='#5eead4'/><ellipse id='e' fill='#fde68a'/><rect id='r' width='60' height='60' fill='#fca5a5'/><path id='p' fill='none'/>"
    end
    paragraph: content = "Point at the circle: its radius is a CSS property here." end
end

Write the path in d with C or L rather than Q. A number followed by a space and Q can be read by the page compiler as the length unit q, which breaks the path. This only happens in CSS written with the page language: the d attribute inside the raw markup is passed on untouched.

Gradients and filters are written in the raw markup too, but their colors are CSS properties. stop color and stop opacity color a gradient stop, flood color and flood opacity color an feFlood step of a filter, and lighting color does so for the lighting steps. color interpolation filters picks the color space in which a filter works, sRGB or linearRGB. Because stops and filter steps are not inherited, you reach them through global rules again.

web-more-svg-paint.salam
page:
    title = "Gradient stops and filters"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    global: selector = ".s1" stop color = "#0f766e" stop opacity = 1 end
    global: selector = ".s2" stop color = "#2563eb" stop opacity = 0.25 end
    global: selector = ".tint" flood color = "#7c3aed" flood opacity = 0.5 end
    global: selector = "filter" color interpolation filters = sRGB end
    svg: view box = "0 0 220 120" width = 220 height = 120
        content = "<defs><linearGradient id='g' x1='0' x2='1'><stop class='s1' offset='0'/><stop class='s2' offset='1'/></linearGradient><filter id='f'><feFlood class='tint' result='c'/><feComposite in='c' in2='SourceGraphic' operator='in' result='t'/><feMerge><feMergeNode in='SourceGraphic'/><feMergeNode in='t'/></feMerge></filter></defs><rect x='5' y='10' width='100' height='100' rx='10' fill='url(#g)'/><rect x='115' y='10' width='100' height='100' rx='10' fill='#38bdf8' filter='url(#f)'/>"
    end
    paragraph: content = "Left: a gradient whose stops are colored with CSS. Right: a filter whose flood color comes from CSS." end
end

Markers are small shapes drawn on the points of a line. marker start, marker mid and marker end take url(#id) of a marker element, and the shorthand marker sets all three at once. Put the marker elements in a separate svg as the example does, because markers inherit the stroke and the marker properties of the drawing they sit in. vector effect = "non-scaling-stroke" keeps a line the same thickness when the drawing is scaled, and shape rendering and color interpolation are hints for how edges and gradients are drawn.

web-more-svg-markers.salam
page:
    title = "Markers on a line"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    svg: width = 0 height = 0 position = absolute
        content = "<defs><marker id='start' viewBox='0 0 10 10' refX='5' refY='5' markerWidth='6' markerHeight='6'><circle cx='5' cy='5' r='5' fill='#2563eb'/></marker><marker id='mid' viewBox='0 0 10 10' refX='5' refY='5' markerWidth='5' markerHeight='5'><rect width='10' height='10' fill='#f59e0b'/></marker><marker id='end' viewBox='0 0 10 10' refX='8' refY='5' markerWidth='8' markerHeight='8' orient='auto'><path d='M0 0 L10 5 L0 10 z' fill='#dc2626'/></marker></defs>"
    end
    svg: view box = "0 0 300 120" width = 300 height = 120 fill = none stroke = "#0f766e" stroke width = 3 marker start = "url(#start)" marker mid = "url(#mid)" marker end = "url(#end)"
        content = "<polyline points='20,90 100,30 180,80 270,30'/>"
    end
    paragraph: content = "A dot at the start, squares at the corners, an arrow at the end." end
end

Math

The math element draws a formula. Like svg, its content is raw markup, here MathML, such as <mfrac> for a fraction and <msup> for a power. Three properties change how it is set. math style is normal for a display formula, with large operators and limits above and below, or compact for one inside a line of text, with everything tighter. math depth says how deeply the formula is nested, so that it can be drawn smaller. It changes the size only where font-size is the keyword math, which the page language does not accept yet, so the example sets it in a raw style element. math shift chooses how far superscripts are raised: compact raises them less, as in the denominator of a fraction.

web-more-math.salam
page:
    title = "Math styles"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    global: selector = "math" font size = "1.6rem" margin = "0 1.5rem 0 0" end
    paragraph: content = "Math style: normal, then compact" end
    box: display = flex
        math: math style = normal
            content = "<munderover><mo>&#x2211;</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><mfrac><mn>1</mn><mi>i</mi></mfrac>"
        end
        math: math style = compact
            content = "<munderover><mo>&#x2211;</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><mfrac><mn>1</mn><mi>i</mi></mfrac>"
        end
    end
    style: content = "#d0, #d1, #d2 { font-size: math }" end
    paragraph: content = "Math depth 0, 1 and 2 side by side" end
    box: display = flex align items = baseline font size = "3rem"
        math: id = "d0" math depth = 0 content = "<mi>x</mi><mo>+</mo><mn>1</mn>" end
        math: id = "d1" math depth = 1 content = "<mi>x</mi><mo>+</mo><mn>1</mn>" end
        math: id = "d2" math depth = 2 content = "<mi>x</mi><mo>+</mo><mn>1</mn>" end
    end
end

Reading order, the top layer and HDR

Keyboard focus and screen readers move through a page in the order of the source. When a layout changes the visual order, for example with flex direction = row-reverse, the two disagree and a keyboard user jumps around the screen. reading flow on the container fixes that: flex-visual follows what is drawn, grid-rows and grid-columns do the same for a grid, and source-order lets the reading order number of each child decide, lowest first. In the example press Tab: the first row is read in source order, the second in the order you see.

web-more-reading.salam
import dom

page:
    title = "Reading order"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    paragraph: id = "out" content = "Press Tab and watch the focus." end
    box: display = flex flex direction = row-reverse gap = 8 margin = "0 0 1rem"
        button: focus = (): dom.SetText(dom.ById("out"), "Focus: A") end content = "A" end
        button: focus = (): dom.SetText(dom.ById("out"), "Focus: B") end content = "B" end
        button: focus = (): dom.SetText(dom.ById("out"), "Focus: C") end content = "C" end
    end
    box: display = flex flex direction = row-reverse gap = 8 reading flow = flex-visual
        button: focus = (): dom.SetText(dom.ById("out"), "Focus: D") end content = "D" end
        button: focus = (): dom.SetText(dom.ById("out"), "Focus: E") end content = "E" end
        button: focus = (): dom.SetText(dom.ById("out"), "Focus: F") end content = "F" end
    end
end

In a right to left page the visual order starts at the right, so the same property gives a different sequence, and the Persian version of this example shows it. Two more properties are for special cases. overlay reports whether an element is in the top layer, where popovers and dialogs are drawn; you list it in a transition so that an element leaving the top layer can finish its exit animation first. dynamic range limit limits how bright HDR images and video may get on a screen that supports it, from standard to no-limit.

Reference: the remaining properties

Every property of this lesson is below with its Persian name, the CSS name, what it accepts and an example that the compiler has checked. A bare number is a length in pixels, and any CSS keyword can be written without quotes unless it is also a word of the page language, such as end, in which case put it in quotes.

Lists, counters and quotes

PropertyWhat it does and what it acceptsExample
list style
سبک فهرست
list-style
Shorthand for list-style-type, list-style-position and list-style-image. Give the parts in any order, for example square inside; a part you leave out keeps its default. [CSS-wide keywords only]list: list style = "square inside" background = "#ccfbf1" padding = 8 item: content = "Sugar" end item: content = "Flour" end end
list style type
نوع نشانه فهرست
list-style-type
The look of the marker. Use a keyword such as disc, circle, square, decimal, decimal-leading-zero, lower-roman, upper-alpha, persian, or none. A text in quotes is used as it is. Set it on the list; the items inherit it. [string / disc, circle, square, decimal, decimal-leading-zero, lower-roman, ...]ordered list: list style type = "upper-alpha" item: content = "Soup" end item: content = "Salad" end end
list style position
جای نشانه فهرست
list-style-position
Where the marker goes. outside (the default) hangs it outside the text box, so wrapped lines stay aligned. inside puts it in the first line of the text, and wrapped lines start under it. [inside, outside]ordered list: list style position = "inside" background = "#e2e8f0" max width = 220 item: content = "A long step that wraps onto a second line" end end
list style image
تصویر نشانه فهرست
list-style-image
Uses a picture as the marker of every list item. The value is an image, such as url(star.png) or a gradient, or none to go back to list-style-type. [image / none]list: list style image = "linear-gradient(#f59e0b, #dc2626)" item: content = "Gold marker" end item: content = "Same marker again" end end
marker
نشانه
marker
An SVG shorthand that sets marker-start, marker-mid and marker-end to the same marker in one go, for example url(#dot). It works on the shapes path, line, polyline and polygon. It has nothing to do with the ::marker of list items. [image]svg: view box = "0 0 60 40" width = 120 height = 80 fill = none stroke = "#0f766e" marker = "url(#dot)" content = "<defs><marker id='dot' viewBox='0 0 10 10' refX='5' refY='5' markerWidth='5' markerHeight='5'><circle cx='5' cy='5' r='5' fill='#dc2626'/></marker></defs><polyline points='5,30 30,8 55,30'/>" end
quotes
نقل قول‌ها
quotes
The quotation marks that quote and the open-quote and close-quote values use. Give pairs of strings: the first pair for the outer level, the second for a quote inside a quote, and so on. none shows no marks and auto picks the marks of the language. [string; up to 99 values]quote: quotes = `"«" "»"` content = "Slow and steady" end
counter reset
بازنشانی شمارنده
counter-reset
Creates a counter on the element, or sets an existing one back to a number. Write the name and, if you want, the start value: chapter starts at 0 and chapter 4 starts at 4. Several counters can be listed together, and none does nothing. [name / integer; up to 99 values]box: counter reset = "n 4" paragraph: counter increment = n before generated content = "counter(n) \". \"" content = "Fifth" end paragraph: counter increment = n before generated content = "counter(n) \". \"" content = "Sixth" end end
counter increment
افزایش شمارنده
counter-increment
Adds to a counter each time the element is drawn. Write the name and, if you want, the step: step adds 1, step 2 adds 2 and step -1 counts down. The number is shown with counter() in generated content. [name / integer; up to 99 values]box: counter reset = step paragraph: counter increment = "step 2" before generated content = "counter(step) \". \"" content = "Two" end paragraph: counter increment = "step 2" before generated content = "counter(step) \". \"" content = "Four" end end
counter set
تنظیم شمارنده
counter-set
Sets a counter to a number without adding to it. Write the name and the value: page 41. The elements after it continue from that number. If no counter of that name exists yet, one is created. [name / integer; up to 99 values]box: counter reset = page paragraph: counter set = "page 41" before generated content = "\"p. \" counter(page)" content = "Jump to page 41" end end

Tables

PropertyWhat it does and what it acceptsExample
border collapse
ادغام کادر
border-collapse
How cell borders meet in a table. collapse merges neighbouring borders into one line. separate (the default) gives every cell its own border with a gap between, which border-spacing controls. [collapse, separate]table: border collapse = "collapse" row: cell: border = "2px solid #0f766e" content = "One" end cell: border = "2px solid #0f766e" content = "Two" end end end
border spacing
فاصله کادرها
border-spacing
The gap between cells when borders are separate. One length is used both ways, and two lengths mean horizontal and then vertical. It has no effect when border-collapse is collapse. [length; up to 2 values]table: border collapse = separate border spacing = "12 4" row: cell: border = "2px solid #2563eb" content = "Left" end cell: border = "2px solid #2563eb" content = "Right" end end end
caption side
جای عنوان جدول
caption-side
Puts the table caption above (top, the default) or below (bottom) the table. Set it on the caption. [top, bottom]table: caption: caption side = "bottom" content = "Prices in euro" end row: cell: content = "Tea 2" end end end
empty cells
خانه‌های خالی
empty-cells
Whether borders and background of empty cells are drawn, in a table with separate borders. show (the default) draws them and hide leaves an empty cell blank. [show, hide]table: border collapse = separate empty cells = "hide" row: cell: border = "2px solid #c2410c" content = "Full" end cell: border = "2px solid #c2410c" end end end
table layout
چیدمان جدول
table-layout
How column widths are found. auto (the default) measures all the content, so a long cell can widen its column. fixed takes widths from the table width and the first row only, which is faster and keeps the table the size you gave it. [auto, fixed]table: table layout = "fixed" width = 200 row: cell: border = "1px solid #64748b" content = "A very long word in a narrow cell" end cell: border = "1px solid #64748b" content = "Short" end end end

Scroll snap and scroll markers

The first three go on the container and its children as described above. The last two build the dots and the highlighted links that follow the scroll.

PropertyWhat it does and what it acceptsExample
scroll snap type
نوع چسبیدن پیمایش
scroll-snap-type
Turns a scroll container into one that snaps. Give the axis (x, y, block, inline or both) and how strict it is: mandatory always rests on a snap point, proximity only when it ends close to one. none turns snapping off. The children choose the points with scroll-snap-align. [CSS-wide keywords only]box: scroll snap type = "y mandatory" overflow y = auto height = 80 box: height = 80 scroll snap align = "start" background = "#99f6e4" content = "First" end box: height = 80 scroll snap align = "start" background = "#bae6fd" content = "Second" end end
scroll snap align
تراز چسبیدن پیمایش
scroll-snap-align
Which part of the child lines up with the snap area of its container: start, center or end, or none for no snap point. Two values set the block and the inline direction separately. It works only inside a container that has scroll-snap-type. [none, start, end, center; up to 2 values]box: scroll snap type = "x mandatory" overflow x = auto display = flex width = 220 box: flex = "0 0 120" scroll snap align = "center" background = "#fde68a" content = "Centered" end box: flex = "0 0 120" scroll snap align = "center" background = "#fecaca" content = "Also centered" end end
scroll snap stop
توقف چسبیدن پیمایش
scroll-snap-stop
Whether a fast scroll may skip past this snap point. normal lets it skip, always makes it stop at this child every time, which suits slide shows and pickers. [normal, always]box: scroll snap type = "x mandatory" overflow x = auto display = flex width = 200 box: flex = "0 0 100%" scroll snap align = "start" scroll snap stop = "always" content = "One" end box: flex = "0 0 100%" scroll snap align = "start" scroll snap stop = "always" content = "Two" end end
scroll marker group
گروه نشانگر پیمایش
scroll-marker-group
Chromium only. On a scroll container, makes the browser build a group of small clickable markers, one for each child that has a ::scroll-marker. before or after says where the group goes around the container, and none turns it off. Style the group with ::scroll-marker-group in raw CSS. [none / before / after]box: scroll marker group = "after" overflow x = auto display = flex scroll snap type = "x mandatory" width = 200 box: flex = "0 0 100%" scroll snap align = "start" content = "Slide one" end box: flex = "0 0 100%" scroll snap align = "start" content = "Slide two" end end
scroll target group
گروه هدف پیمایش
scroll-target-group
Chromium only. auto turns an element that holds links into a group of scroll targets: every link inside that points to a place on the same page counts as a scroll marker, and the link whose target is in view matches :target-current, so you can highlight it. none (the default) does nothing. Used for tables of contents that follow the scroll. [auto / none]list: scroll target group = "auto" item: link: url = "#intro" content = "Introduction" end end item: link: url = "#usage" content = "Usage" end end end

Scroll margin

Set on the child. The sides are physical (top, right, bottom, left) or logical (block and inline, with start and end).

PropertyWhat it does and what it acceptsExample
scroll margin
فضا پیمایش
scroll-margin
Extra room around a child that counts as part of its snap area, so a snap or a jump to it stops a little short. One to four lengths, like margin. It is set on the child, not on the container. [length; up to 4 values]box: scroll snap align = "start" scroll margin = 16 background = "#ddd6fe" padding = 12 content = "Stops 16px short" end
scroll margin top
فضا پیمایش بالا
scroll-margin-top
Scroll margin on the top edge of the child. One length. A common use is keeping a linked heading clear of a fixed header when the page jumps to it. [length]heading: size = 2 id = "prices" scroll margin top = 72 content = "Prices" end
scroll margin right
فضا پیمایش راست
scroll-margin-right
Scroll margin on the right edge of the child, whatever the writing direction. One length. [length]box: scroll snap align = "end" scroll margin right = 24 background = "#fecdd3" padding = 12 content = "24px on the right" end
scroll margin bottom
فضا پیمایش پایین
scroll-margin-bottom
Scroll margin on the bottom edge of the child. One length. [length]box: scroll snap align = "end" scroll margin bottom = 10 background = "#e9d5ff" padding = 10 content = "Bottom margin 10" end
scroll margin left
فضا پیمایش چپ
scroll-margin-left
Scroll margin on the left edge of the child, whatever the writing direction. One length. [length]box: scroll snap align = "start" scroll margin left = 24 background = "#bfdbfe" padding = 12 content = "24px on the left" end
scroll margin block
فضا پیمایش بلوکی
scroll-margin-block
Scroll margin in the block direction, start and end together: one length for both sides or two, start then end. In English text the block direction is top and bottom. [length; up to 2 values]box: scroll snap align = "start" scroll margin block = "8 24" background = "#bbf7d0" padding = 12 content = "Room above and below" end
scroll margin block start
فضا پیمایش بلوکی ابتدا
scroll-margin-block-start
Scroll margin at the start of the block direction, which is the top in horizontal English text. Useful for a heading that must not hide under a sticky bar. [length]heading: size = 3 scroll margin block start = 64 content = "Section title" end
scroll margin block end
فضا پیمایش بلوکی انتها
scroll-margin-block-end
Scroll margin at the end of the block direction, which is the bottom in horizontal English text. [length]box: scroll snap align = "end" scroll margin block end = 20 background = "#fed7aa" padding = 12 content = "20px kept at the end" end
scroll margin inline
فضا پیمایش خطی
scroll-margin-inline
Scroll margin in the inline direction, start and end together: one length for both or two, start then end. In English text the inline direction is left and right. [length; up to 2 values]box: scroll snap align = center scroll margin inline = "12 12" background = "#a5f3fc" padding = 12 content = "Sideways room" end
scroll margin inline start
فضا پیمایش ابتدا
scroll-margin-inline-start
Scroll margin at the start of the inline direction: the left in left to right text and the right in right to left text. [length]box: scroll snap align = "start" scroll margin inline start = 30 background = "#fef08a" padding = 12 content = "Room at the start" end
scroll margin inline end
فضا پیمایش انتها
scroll-margin-inline-end
Scroll margin at the end of the inline direction: the right in left to right text and the left in right to left text. [length]box: scroll snap align = "end" scroll margin inline end = 30 background = "#fbcfe8" padding = 12 content = "Room at the end" end

Scroll padding

Set on the scroll container, with the same sides as scroll margin. Percentages refer to the size of the container.

PropertyWhat it does and what it acceptsExample
scroll padding
فاصله پیمایش
scroll-padding
Room kept free at the edges of a scroll container when it snaps or jumps to a child, so the child does not touch the edge or hide under a fixed bar. One to four lengths or percentages, like padding, or auto. It is set on the container. [length / percentage / auto; up to 4 values]box: scroll snap type = "x mandatory" scroll padding = "0 24" overflow x = auto display = flex width = 200 box: flex = "0 0 160" scroll snap align = "start" background = "#99f6e4" content = "One" end box: flex = "0 0 160" scroll snap align = "start" background = "#bae6fd" content = "Two" end end
scroll padding top
فاصله پیمایش بالا
scroll-padding-top
Scroll padding on the top edge of a scroll container. Set it to the height of a sticky header so that a jump or a snap does not hide the target under it. A length, a percentage or auto. [length / percentage / auto]global: selector = "html" scroll padding top = 64 end heading: size = 2 id = "faq" content = "Questions" end
scroll padding right
فاصله پیمایش راست
scroll-padding-right
Scroll padding on the right edge of a scroll container, whatever the writing direction. A length, a percentage or auto. [length / percentage / auto]box: scroll snap type = "x mandatory" scroll padding right = 40 overflow x = auto display = flex width = 200 box: flex = "0 0 150" scroll snap align = "end" background = "#fecdd3" content = "Right gap 40" end end
scroll padding bottom
فاصله پیمایش پایین
scroll-padding-bottom
Scroll padding on the bottom edge of a scroll container. A length, a percentage or auto. [length / percentage / auto]box: scroll padding bottom = "20%" overflow y = auto height = 100 border = "1px solid #94a3b8" paragraph: content = "The last paragraph stops above the bottom edge." end end
scroll padding left
فاصله پیمایش چپ
scroll-padding-left
Scroll padding on the left edge of a scroll container, whatever the writing direction. A length, a percentage or auto. [length / percentage / auto]box: scroll snap type = "x mandatory" scroll padding left = "10%" overflow x = auto display = flex width = 200 box: flex = "0 0 150" scroll snap align = "start" background = "#bfdbfe" content = "Left gap 10%" end end
scroll padding block
فاصله پیمایش بلوکی
scroll-padding-block
Scroll padding in the block direction, start and end together: one value for both or two, start then end. Lengths, percentages or auto. [length / percentage / auto; up to 2 values]box: scroll snap type = "y mandatory" scroll padding block = "10 20" overflow y = auto height = 100 box: height = 90 scroll snap align = "start" background = "#fde68a" content = "Row one" end box: height = 90 scroll snap align = "start" background = "#fecaca" content = "Row two" end end
scroll padding block start
فاصله پیمایش بلوکی ابتدا
scroll-padding-block-start
Scroll padding at the start of the block direction of a scroll container, the top in horizontal English text. A length, a percentage or auto. [length / percentage / auto]box: scroll padding block start = 48 overflow y = auto height = 120 heading: size = 3 id = "part" content = "A part" end end
scroll padding block end
فاصله پیمایش بلوکی انتها
scroll-padding-block-end
Scroll padding at the end of the block direction of a scroll container, the bottom in horizontal English text. A length, a percentage or auto. [length / percentage / auto]box: scroll snap type = "y proximity" scroll padding block end = 40 overflow y = auto height = 100 box: height = 90 scroll snap align = "end" background = "#bbf7d0" content = "Keeps 40px free below" end end
scroll padding inline
فاصله پیمایش خطی
scroll-padding-inline
Scroll padding in the inline direction, start and end together: one value for both or two, start then end. Lengths, percentages or auto. [length / percentage / auto; up to 2 values]box: scroll snap type = "x mandatory" scroll padding inline = "16 32" overflow x = auto display = flex width = 200 box: flex = "0 0 150" scroll snap align = center background = "#a5f3fc" content = "Card" end end
scroll padding inline start
فاصله پیمایش ابتدا
scroll-padding-inline-start
Scroll padding at the start of the inline direction of a scroll container: the left in left to right text. A length, a percentage or auto. [length / percentage / auto]box: scroll snap type = "x mandatory" scroll padding inline start = 30 overflow x = auto display = flex width = 200 box: flex = "0 0 150" scroll snap align = "start" background = "#fef08a" content = "First card" end end
scroll padding inline end
فاصله پیمایش انتها
scroll-padding-inline-end
Scroll padding at the end of the inline direction of a scroll container: the right in left to right text. A length, a percentage or auto. [length / percentage / auto]box: scroll snap type = "x proximity" scroll padding inline end = 30 overflow x = auto display = flex width = 200 box: flex = "0 0 150" scroll snap align = "end" background = "#fbcfe8" content = "Last card" end end

Anchor positioning

PropertyWhat it does and what it acceptsExample
anchor name
نام لنگر
anchor-name
A newer feature: Chromium browsers have it and others are catching up. Gives an element a name that other elements can position themselves against. The name starts with two hyphens, like --menu. A list of names gives the element several, and none removes them. [dashed ident list / none]button: anchor name = "--menu" content = "Menu" end
anchor scope
دامنه لنگر
anchor-scope
A newer feature: Chromium browsers have it and others are catching up. Limits where anchor names are visible. With names, only the subtree of this element sees those anchors; with all, every name defined inside stays inside. It lets many copies of a component each use the same name without mixing up. [dashed ident list / all]box: anchor scope = "all" button: anchor name = "--tip" content = "Help" end end
position anchor
لنگر جایگاه
position-anchor
A newer feature: Chromium browsers have it and others are catching up. Chooses which anchor name an absolutely or fixed positioned element is placed against. Give a dashed name like --menu, or auto to use the anchor the browser links to it, such as the button of a popover. [dashed ident / auto]box: position = absolute position anchor = "--menu" position area = bottom background = "#0f172a" color = white padding = 6 content = "Under the menu button" end
position area
ناحیه جایگاه
position-area
A newer feature: Chromium browsers have it and others are catching up. Places an anchored element in one cell of a 3 by 3 grid around its anchor. Use top, bottom, left, right and center, or two of them like top right. A word with span- takes two cells, for example top span-right. [up to 2 keywords (top, span-right, center, ...)]box: position = absolute position anchor = "--card" position area = "top span-right" background = "#0f766e" color = white padding = 6 content = "Above, stretching right" end
position try fallbacks
جایگزین های جایگاه
position-try-fallbacks
A newer feature: Chromium browsers have it and others are catching up. A comma separated list of other places to try when the element would run out of the screen. Use the tactics flip-block, flip-inline and flip-start, a position-area value, or the name of a @position-try rule. The first one that fits is used. [comma list of tactics and/or position-area values]box: position = absolute position anchor = "--tip" position area = top position try fallbacks = "flip-block, bottom" content = "Moves below if there is no room" end
position try order
ترتیب تلاش جایگاه
position-try-order
A newer feature: Chromium browsers have it and others are catching up. Decides how the fallbacks of position-try-fallbacks are ranked. normal tries them in the order written. most-width, most-height, most-block-size and most-inline-size pick the one that leaves the most room in that direction. [normal / most-width / most-height / most-block-size / most-inline-size]box: position = absolute position anchor = "--tip" position area = left position try order = "most-width" position try fallbacks = "right, top" content = "Picks the widest side" end
position try
تلاش جایگاه
position-try
A newer feature: Chromium browsers have it and others are catching up. Shorthand for position-try-order and position-try-fallbacks. The order word, if any, comes first, then the list of fallbacks. [position-try-order then position-try-fallbacks, shorthand]box: position = absolute position anchor = "--tip" position area = top position try = "most-height flip-block" content = "Tries the taller side first" end
position visibility
پیدایی جایگاه
position-visibility
A newer feature: Chromium browsers have it and others are catching up. When an anchored element is hidden. always never hides it, anchors-visible hides it when its anchor scrolls out of view, and no-overflow hides it when it would overflow its containing block. [up to 2 of always, anchors-visible, no-overflow]box: position = absolute position anchor = "--note" position area = right position visibility = "anchors-visible" content = "Hidden when the anchor is off screen" end

SVG fill and stroke

PropertyWhat it does and what it acceptsExample
fill
پرکردن
fill
The color that fills the inside of an SVG shape or SVG text. A color, none for no fill, or url(#id) to use a gradient or pattern. It is inherited, so setting it on the svg element paints every shape inside. [color / none]svg: view box = "0 0 40 40" width = 80 height = 80 fill = "#f97316" content = "<circle cx='20' cy='20' r='16'/>" end
fill opacity
شفافیت پرکردن
fill-opacity
How see-through the fill of an SVG shape is, from 0 (invisible) to 1 (solid), or as a percentage. The outline is not affected. [number / percentage]svg: view box = "0 0 40 40" width = 80 height = 80 fill = "#2563eb" fill opacity = 0.4 stroke = "#1e3a8a" stroke width = 2 content = "<rect x='6' y='6' width='28' height='28' rx='4'/>" end
fill rule
قاعده پرکردن
fill-rule
Decides which points count as inside a shape that crosses itself. nonzero (the default) fills everything the path winds around. evenodd leaves a hole wherever the path crosses itself, like the middle of a star. [nonzero, evenodd]svg: view box = "0 0 40 40" width = 80 height = 80 fill = "#14b8a6" fill rule = "evenodd" content = "<polygon points='20,3 32,37 3,15 37,15 8,37'/>" end
clip rule
قاعده برش
clip-rule
The same choice as fill-rule, but for the shape used inside a clipPath: nonzero or evenodd decides which parts of the clipping shape let the picture show through. [nonzero, evenodd]svg: view box = "0 0 40 40" width = 80 height = 80 clip rule = "evenodd" content = "<defs><clipPath id='c'><polygon points='20,3 32,37 3,15 37,15 8,37' style='clip-rule:inherit'/></clipPath></defs><rect width='40' height='40' fill='#7c3aed' clip-path='url(#c)'/>" end
stroke
خط دور
stroke
The color of the line drawn along the edge of an SVG shape or text. A color, none for no line, or url(#id) for a gradient. Without a stroke only the fill shows. It is inherited. [color / none]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#dc2626" stroke width = 3 content = "<circle cx='20' cy='20' r='14'/>" end
stroke width
ضخامت خط دور
stroke-width
The thickness of the outline of an SVG shape, as a length or a percentage of the drawing size. The default is 1. A line is centred on the edge, so half of it falls inside the shape. [length / percentage]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#0f766e" stroke width = 6 content = "<rect x='8' y='8' width='24' height='24'/>" end
stroke opacity
شفافیت خط دور
stroke-opacity
How see-through the outline of an SVG shape is, from 0 to 1 or as a percentage. The fill is not affected. [number / percentage]svg: view box = "0 0 40 40" width = 80 height = 80 fill = "#fde68a" stroke = "#7c2d12" stroke width = 6 stroke opacity = 0.35 content = "<circle cx='20' cy='20' r='13'/>" end
stroke dasharray
الگوی خط‌چین خط دور
stroke-dasharray
Turns the outline into dashes. A list of lengths that alternate between a dash and a gap, for example 6 3. An odd number of values is repeated to make it even. none draws a solid line. [length / percentage / number; up to 99 values; comma list]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#2563eb" stroke width = 3 stroke dasharray = "6 3" content = "<line x1='4' y1='20' x2='36' y2='20'/>" end
stroke dashoffset
فاصله خط‌چین
stroke-dashoffset
Where in the dash pattern the line starts: a length or percentage that shifts the pattern along the line. Changing it over time makes marching ants and line drawing animations. [length / percentage]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#c2410c" stroke width = 3 stroke dasharray = "8 4" stroke dashoffset = 6 content = "<line x1='4' y1='20' x2='36' y2='20'/>" end
stroke linecap
سر خط دور
stroke-linecap
The shape of the two ends of an open line: butt (flat, the default), round (a half circle) or square (flat, but longer by half the width). [butt, round, square]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#0f766e" stroke width = 8 stroke linecap = "round" content = "<line x1='10' y1='20' x2='30' y2='20'/>" end
stroke linejoin
اتصال خط دور
stroke-linejoin
The shape of a corner where two segments of a line meet: miter (a sharp point, the default), round or bevel (cut flat). [miter, round, bevel]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#7c3aed" stroke width = 8 stroke linejoin = "round" content = "<polyline points='6,32 20,8 34,32'/>" end
stroke miterlimit
حد گوشه خط دور
stroke-miterlimit
Limits how long a sharp corner may stretch. When the point would be longer than this number times the line width, the corner is cut flat like bevel. A number of 1 or more; the default is 4. [number]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#be123c" stroke width = 6 stroke linejoin = miter stroke miterlimit = 1.5 content = "<polyline points='6,34 20,6 34,34'/>" end
paint order
ترتیب نقاشی
paint-order
The order in which fill, outline and markers of an SVG shape or text are drawn. normal is fill, then stroke, then markers. stroke fill draws the outline first, so the fill covers its inner half and the text looks outlined without thinning. [up to 3 values]svg: view box = "0 0 40 40" width = 80 height = 80 font size = 28 font weight = bold fill = "#fde68a" stroke = "#0f172a" stroke width = 5 paint order = "stroke fill" content = "<text x='4' y='30'>Ab</text>" end

SVG text and baselines

PropertyWhat it does and what it acceptsExample
text anchor
لنگر متن
text-anchor
Which part of an SVG text sits on its x point: start (the text begins there), middle (the text is centred on it) or end (the text ends there). It is inherited. [start / middle / end]svg: view box = "0 0 40 40" width = 80 height = 80 font size = 10 text anchor = "middle" content = "<text x='20' y='24'>Mid</text>" end
dominant baseline
خط پایه غالب
dominant-baseline
Which baseline an SVG text uses to line up its letters with its y point. auto and alphabetic use the bottom of the letters, middle and central use the middle, and hanging uses the top line of scripts such as Devanagari. [a baseline keyword (middle, central, alphabetic, ...)]global: selector = "text" dominant baseline = "middle" end svg: view box = "0 0 60 30" width = 120 height = 60 font size = 12 content = "<line x1='0' y1='15' x2='60' y2='15' stroke='#ef4444' stroke-width='0.5'/><text x='4' y='15'>Mid</text>" end
alignment baseline
خط پایه تراز
alignment-baseline
How a piece of inline content, such as a tspan, lines its own baseline up with the one of its parent. baseline is the default; middle, central, alphabetic and text-top pick another. [a baseline keyword (middle, central, alphabetic, ...)]global: selector = "tspan" alignment baseline = "middle" font size = 8 end svg: view box = "0 0 80 30" width = 160 height = 60 font size = 16 content = "<text x='4' y='20'>Big<tspan>small</tspan></text>" end
baseline shift
جابه‌جایی خط پایه
baseline-shift
Raises or lowers text from its baseline. A length or percentage (positive is up), or the words sub, super, top, center and bottom. It is how SVG text makes powers and indices. [length / percentage / sub / super / top / center / bottom]global: selector = "tspan" baseline shift = "super" font size = 9 end svg: view box = "0 0 60 30" width = 120 height = 60 font size = 16 content = "<text x='6' y='22'>m<tspan>2</tspan></text>" end
baseline source
منبع خط پایه
baseline-source
Not every browser has it (Chromium does). For an inline block with several lines, tells which line gives the baseline that is lined up with the surrounding text: first, last, or auto which depends on the kind of box. [auto / first / last]paragraph: content = "Text before" span: display = inline-block baseline source = "last" border = "1px solid #64748b" content = "First line, and a second line" max width = 80 end end

SVG geometry and drawing hints

PropertyWhat it does and what it acceptsExample
cx
مرکز x
cx
The x position of the centre of an SVG circle or ellipse, as a length or percentage of the width. It is a CSS property in modern browsers, so a rule can move a shape without touching its markup. [length / percentage]global: selector = "#dot" cx = 30 end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<circle id='dot' cy='20' r='12' fill='#14b8a6'/>" end
cy
مرکز y
cy
The y position of the centre of an SVG circle or ellipse, as a length or percentage of the height. [length / percentage]global: selector = "#dot" cy = "25%" end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<circle id='dot' cx='30' r='9' fill='#f97316'/>" end
r
شعاع
r
The radius of an SVG circle, as a length or percentage. A percentage refers to the diagonal of the drawing area. [length / percentage]global: selector = "#dot" r = 15 end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<circle id='dot' cx='30' cy='20' fill='#6366f1'/>" end
rx
شعاع x
rx
The horizontal radius of an SVG ellipse, or the horizontal rounding of the corners of a rect. A length, a percentage or auto. [length / percentage / auto]global: selector = "#r" rx = 12 end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<rect id='r' x='8' y='8' width='44' height='24' fill='#ec4899'/>" end
ry
شعاع y
ry
The vertical radius of an SVG ellipse, or the vertical rounding of the corners of a rect. A length, a percentage or auto. [length / percentage / auto]global: selector = "#e" rx = 24 ry = 10 end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<ellipse id='e' cx='30' cy='20' fill='#84cc16'/>" end
x
مختصات x
x
The x position of the top left corner of an SVG rect, image, nested svg or foreignObject, as a length or percentage. [length / percentage]global: selector = "#r" x = 20 end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<rect id='r' y='10' width='24' height='20' fill='#f43f5e'/>" end
y
مختصات y
y
The y position of the top left corner of an SVG rect, image, nested svg or foreignObject, as a length or percentage. [length / percentage]global: selector = "#r" y = 15 end svg: view box = "0 0 60 40" width = 120 height = 80 content = "<rect id='r' x='18' width='24' height='20' fill='#0ea5e9'/>" end
d
داده مسیر
d
The outline of an SVG path written in CSS: path("M 10 30 L 30 10 L 50 30"), using the same commands as the d attribute, or none. Because it is CSS, it can be animated and changed on hover. Avoid the command Q right after a number: the page compiler can read that pair as the length unit q, so use C or L instead. [path() / none]global: selector = "#p" d = "path('M 5 30 L 20 8 L 35 30 Z')" end svg: view box = "0 0 40 40" width = 80 height = 80 fill = "#fb923c" content = "<path id='p'/>" end
vector effect
جلوه برداری
vector-effect
Changes how an SVG shape is drawn when it is scaled. none scales everything. non-scaling-stroke keeps the line width constant on the screen while the shape grows or shrinks. [none / non-scaling-stroke]global: selector = "rect" vector effect = "non-scaling-stroke" end svg: view box = "0 0 10 10" width = 100 height = 100 fill = "#bae6fd" stroke = "#0369a1" stroke width = 2 content = "<rect x='1' y='1' width='8' height='8'/>" end
shape rendering
پرداخت شکل
shape-rendering
A hint for how the edges of SVG shapes are drawn. auto is the default, optimizeSpeed skips smoothing, crispEdges avoids blur on straight lines and geometricPrecision favours exact shapes. Browsers may treat some values alike. [auto / optimizeSpeed / crispEdges / geometricPrecision]svg: view box = "0 0 40 40" width = 80 height = 80 fill = "#bbf7d0" stroke = "#166534" shape rendering = "crispEdges" content = "<rect x='5.5' y='5.5' width='29' height='29'/>" end
color interpolation
میان‌یابی رنگ
color-interpolation
The color space in which SVG blends colors for things like gradients and masks: sRGB, linearRGB or auto. Support is patchy, so check the result in the browsers you target. [auto / sRGB / linearRGB]global: selector = "linearGradient" color interpolation = "linearRGB" end svg: view box = "0 0 40 20" width = 120 height = 60 content = "<defs><linearGradient id='g'><stop offset='0' stop-color='red'/><stop offset='1' stop-color='blue'/></linearGradient></defs><rect width='40' height='20' fill='url(#g)'/>" end

Gradients, filters and markers

PropertyWhat it does and what it acceptsExample
stop color
رنگ ایست
stop-color
The color of a stop in an SVG gradient, set on the stop element. Any color. Together with the offset of the stop it says what color the gradient has at that point. [color]global: selector = "#s2" stop color = "#0ea5e9" end svg: view box = "0 0 40 20" width = 120 height = 60 content = "<defs><linearGradient id='g'><stop offset='0' stop-color='#fde047'/><stop id='s2' offset='1'/></linearGradient></defs><rect width='40' height='20' fill='url(#g)'/>" end
stop opacity
شفافیت ایست
stop-opacity
How see-through a gradient stop is, from 0 to 1 or as a percentage. A gradient can fade out by ending in a stop of opacity 0. [number / percentage]global: selector = "#e" stop color = "#dc2626" stop opacity = 0 end svg: view box = "0 0 40 20" width = 120 height = 60 content = "<defs><linearGradient id='g'><stop offset='0' stop-color='#dc2626'/><stop id='e' offset='1'/></linearGradient></defs><rect width='40' height='20' fill='url(#g)'/>" end
flood color
رنگ سیل
flood-color
The color of an feFlood filter step, which fills the whole filter area with one color. Any color. [color]global: selector = "feFlood" flood color = "#f59e0b" end svg: view box = "0 0 40 40" width = 80 height = 80 content = "<defs><filter id='f'><feFlood result='c'/><feComposite in='c' in2='SourceGraphic' operator='in'/></filter></defs><circle cx='20' cy='20' r='14' fill='black' filter='url(#f)'/>" end
flood opacity
شفافیت سیل
flood-opacity
How see-through the color of an feFlood step is, from 0 to 1 or as a percentage. [number / percentage]global: selector = "feFlood" flood color = "#7c3aed" flood opacity = 0.4 end svg: view box = "0 0 40 40" width = 80 height = 80 content = "<defs><filter id='f'><feFlood result='c'/><feComposite in='c' in2='SourceGraphic' operator='in'/></filter></defs><rect x='6' y='6' width='28' height='28' fill='black' filter='url(#f)'/>" end
lighting color
رنگ نورپردازی
lighting-color
The color of the light in the feDiffuseLighting and feSpecularLighting filter steps. Any color; the default is white. [color]global: selector = "feDiffuseLighting" lighting color = "#fde68a" end svg: view box = "0 0 40 40" width = 80 height = 80 content = "<defs><filter id='l'><feDiffuseLighting surfaceScale='3'><feDistantLight azimuth='45' elevation='50'/></feDiffuseLighting></filter></defs><rect width='40' height='40' filter='url(#l)'/>" end
color interpolation filters
میان‌یابی رنگ پالایه
color-interpolation-filters
The color space in which the steps of an SVG filter work: linearRGB (the default for filters), sRGB or auto. Switching to sRGB makes blurs and blends look closer to what design tools show. [auto / sRGB / linearRGB]global: selector = "filter" color interpolation filters = "sRGB" end svg: view box = "0 0 40 40" width = 80 height = 80 content = "<defs><filter id='b'><feGaussianBlur stdDeviation='2'/></filter></defs><circle cx='20' cy='20' r='10' fill='#2563eb' filter='url(#b)'/>" end
marker start
نشانگر آغاز
marker-start
The marker drawn at the first point of an SVG path, line, polyline or polygon. url(#id) of a marker element, or none. [image / none]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#0f766e" stroke width = 2 marker start = "url(#a)" content = "<defs><marker id='a' viewBox='0 0 10 10' refX='5' refY='5' markerWidth='5' markerHeight='5'><circle cx='5' cy='5' r='5' fill='#dc2626'/></marker></defs><polyline points='6,32 20,8 34,32'/>" end
marker mid
نشانگر میانه
marker-mid
The marker drawn at every point between the first and the last of an SVG path, line, polyline or polygon. url(#id) of a marker element, or none. [image / none]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#2563eb" stroke width = 2 marker mid = "url(#b)" content = "<defs><marker id='b' viewBox='0 0 10 10' refX='5' refY='5' markerWidth='5' markerHeight='5'><rect width='10' height='10' fill='#f59e0b'/></marker></defs><polyline points='4,32 14,10 26,30 36,8'/>" end
marker end
نشانگر انتها
marker-end
The marker drawn at the last point of an SVG path, line, polyline or polygon. With orient="auto" on the marker, an arrow head turns to follow the line. url(#id) or none. [image / none]svg: view box = "0 0 40 40" width = 80 height = 80 fill = none stroke = "#7c3aed" stroke width = 2 marker end = "url(#c)" content = "<defs><marker id='c' viewBox='0 0 10 10' refX='8' refY='5' markerWidth='6' markerHeight='6' orient='auto'><path d='M0 0 L10 5 L0 10 z' fill='#7c3aed'/></marker></defs><line x1='4' y1='30' x2='34' y2='10'/>" end

Math

PropertyWhat it does and what it acceptsExample
math style
سبک ریاضی
math-style
Set on a math element: normal draws display style, with large operators and fractions that take their full height. compact draws inline style, which is tighter and fits into a line of text. [normal, compact]math: math style = "compact" font size = 24 content = "<mfrac><mn>1</mn><mn>2</mn></mfrac>" end
math depth
عمق ریاضی
math-depth
The nesting depth of a piece of math, used to shrink text in fractions, powers and indices. A whole number sets the depth, and auto-add lets the browser add a level when the math style is compact. It changes the size only where font-size is math. [integer / auto-add]math: math depth = 2 content = "<mi>x</mi><mo>+</mo><mn>1</mn>" end
math shift
جابه‌جایی ریاضی
math-shift
Set on a math element: normal raises superscripts by the usual amount, and compact raises them less, as math does in cramped places such as under a fraction bar. [normal / compact]math: math shift = "compact" font size = 24 content = "<msup><mi>x</mi><mn>2</mn></msup>" end

Reading order, top layer and HDR

PropertyWhat it does and what it acceptsExample
reading flow
جریان خواندن
reading-flow
Chromium only. Sets the order in which keyboard focus and screen readers move through the children of a flex, grid or block container. normal follows the source. flex-visual, flex-flow, grid-rows, grid-columns and grid-order follow what is drawn, and source-order lets reading-order decide. [normal / source-order / flex and grid flow keywords]box: display = flex flex direction = row-reverse reading flow = "flex-visual" button: content = "One" end button: content = "Two" end end
reading order
ترتیب خواندن
reading-order
Chromium only. A whole number that ranks a child inside a container whose reading-flow is not normal. Lower numbers are read first, and children with the same number keep their source order. The default is 0. [an integer]box: display = flex reading flow = source-order button: reading order = 2 content = "Read second" end button: reading order = 1 content = "Read first" end end
overlay
روکش
overlay
Chromium only. Tells whether an element is shown in the top layer, which is where popovers and dialogs live. You cannot set it for effect: you list it in transition so that an element leaving the top layer stays visible until its exit animation ends. Values are auto and none. [auto / none]box: overlay = "auto" transition = "opacity 0.3s, overlay 0.3s allow-discrete" content = "Fades out in the top layer" end
dynamic range limit
حد بازه پویا
dynamic-range-limit
A new feature that not every browser has. Limits how bright HDR content may be on an HDR screen. standard keeps it as bright as normal content, no-limit allows the full range and constrained is in between. dynamic-range-limit-mix() blends the keywords by percentages. [standard / no-limit / constrained / dynamic-range-limit-mix()]video: source: url = "clip.mp4" end dynamic range limit = "constrained" controls = true end

Try it yourself

  • Make a numbered table of contents for a page with three headings. Use one counter, counter increment on each heading and generated content with counter() to number them.
  • Change the slide strip to a vertical one: scroll snap type = "y mandatory" with overflow y and a fixed height. Then give the container a scroll padding top and see how the slides stop.
  • Add a fifth button to the tooltip example that sets the area to "top right", and a sixth for "bottom span-left". Which cell of the grid does each pick?
  • Draw a house in an svg, a square and a triangle, and give both one fill and stroke on the svg element. Then use a global rule to give only the roof a dashed stroke.