Lesson 34 of 45 · Web pages

Borders, outlines and shadows

The edge of a box is where a design gets its character: a thin line, a rounded card, a glowing ring, a shadow that lifts it off the page. This lesson covers every border, outline and shadow property, shows how the compiler checks your values, and explains why you should never remove a focus ring.

The border shorthand

A border is a line drawn between the padding of a box and its margin. It has three parts: a width, a style and a color. The shorthand border takes all three in one string, in any order: "2px solid #0f766e". A bare number written without quotes, such as 6, means pixels. The style decides what is drawn: solid is a plain line, dashed and dotted are broken lines, double is two thin lines with a gap, and groove, ridge, inset and outset imitate a carved or raised edge by shading two sides lighter and two darker. none draws nothing and hidden does the same, but wins when two borders meet in a table.

web-border-styles.salam
component Sample(kind):
    box:
        border style = kind
        border width = 6
        border color = "#0f766e"
        padding = 12
        content = kind
    end
end

page:
    title = "Border styles"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        display = grid gap = 12 grid template columns = "repeat(auto-fit, minmax(110px, 1fr))" text align = center
        Sample: kind = "solid" end
        Sample: kind = "dashed" end
        Sample: kind = "dotted" end
        Sample: kind = "double" end
        Sample: kind = "groove" end
        Sample: kind = "ridge" end
        Sample: kind = "inset" end
        Sample: kind = "outset" end
    end
end

The example uses a small component, Sample, so each border style is one line. It passes the style name to border style and also shows it as text. The same three parts exist as separate properties: border width, border style and border color.

The style is the part people forget. The default style is none, so border color = "red" or border width = 5 on their own draw nothing at all. Always write a style, either in the shorthand or with border style = solid.

The three longhands take from one to four values, and the rule is the same for each of them. One value applies to all four sides. Two values are the top and bottom, then the left and right. Three values are the top, then the left and right, then the bottom. Four values go clockwise from the top: top, right, bottom, left. Padding and margin use the same rule, so you only learn it once.

A border is part of the box. With the default sizing a box of width = 200 and a border of 6px on each side becomes 212px wide. Many pages add a global rule box sizing = "border-box", which makes the width include padding and border, and the next lessons assume you know both ways.

One side at a time

Each side has its own shorthand and its own three longhands. border top, border right, border bottom and border left take the usual width, style and color. border top color and its twelve relatives change one part of one side. The example shows the most common uses: a thick stripe on the left of a warning, an underline under a heading, and two ways to give the four sides different widths and colors in a single line.

web-border-sides.salam
page:
    title = "Borders on one side"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        display = grid gap = 14
        box: border left = "6px solid #dc2626" background = "#fef2f2" padding = "10px 14px" content = "A warning: border left" end
        heading: size = 3 margin = 0 padding = "0 0 6px 0" border bottom = "3px solid #0f766e" content = "A heading: border bottom" end
        box: border style = "solid" border width = "2px 10px" border color = "#6366f1" padding = 12 content = "Two values: top and bottom, left and right" end
        box: border style = "solid" border width = 6 border color = "#ef4444 #22c55e #3b82f6 #eab308" padding = 12 content = "Four colors: top, right, bottom, left" end
    end
end

When a side has no border you can leave it out. The usual way to build a mixed border is to set border first and then overwrite the one side that must differ, for example border = "1px solid #cbd5e1" followed by border bottom color = "#0f766e". The later property wins, so the order of the lines matters.

Logical sides for any language

left and right are wrong for a page that is read from right to left: a stripe at the left of an English quotation belongs at the right of a Persian one. The logical properties name the sides by the direction of the text instead. The inline direction is the way a line of text runs. Inline start is where a line begins, which is the left in English and the right in Persian or Arabic, and inline end is the opposite side. The block direction is the way lines stack, so block start is the top and block end is the bottom in ordinary horizontal text.

That gives border inline start, border inline end, border block start and border block end, each with its width, style and color. The shorthand border inline sets both inline sides and border block sets both block sides, and their color, style and width forms take one or two values (start, then end). In the example the same line of code puts the stripe on the left of the English box and on the right of the Persian box, because the second box has dir = "rtl".

web-border-logical.salam
page:
    title = "Logical borders"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        dir = "ltr"
        border inline start = "6px solid #0f766e"
        padding = "10px 14px"
        margin = "0 0 14px 0"
        background = "#f0fdfa"
        content = "English text: the stripe is on the left."
    end
    box:
        dir = "rtl"
        border inline start = "6px solid #0f766e"
        padding = "10px 14px"
        background = "#f0fdfa"
        content = "متن فارسی: خط کنار راست است."
    end
end

Prefer the logical names in anything that may be shown in more than one language. In a Persian-only project the physical names are fine, and they are often what you want for something that is tied to the screen, such as a shadow.

Rounded corners

border radius rounds the corners. A single length makes circular corners of that radius. Two to four values follow the corner order: with two, the first is for the top left and bottom right corners and the second for the top right and bottom left; with four they go clockwise from the top left. A slash makes oval corners: 50% / 30% sets a horizontal radius of 50% and a vertical radius of 30%. A radius larger than the box can fit is reduced, so 999px is the usual way to make a pill, and 50% on a square makes a circle.

Each corner also has its own property: border top left radius, border top right radius, border bottom left radius and border bottom right radius, and the logical versions border start start radius, border start end radius, border end start radius and border end end radius. The first word after border is the block side and the second is the inline side, so border start end radius is the top right corner in English and the top left in Persian.

web-border-radius.salam
component Tile(label, corners):
    box:
        width = 100
        height = 70
        background = "#f59e0b"
        display = flex
        align items = center
        justify content = center
        font size = 13
        border radius = corners
        content = label
    end
end

page:
    title = "Rounded corners"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        display = flex gap = 14 flex wrap = wrap
        Tile: label = "12" corners = 12 end
        Tile: label = "30px 0" corners = "30px 0" end
        Tile: label = "pill" corners = "999px" end
        Tile: label = "50% / 30%" corners = "50% / 30%" end
        Tile: label = "4 values" corners = "40px 4px 40px 4px" end
        box: width = 70 height = 70 border radius = "50%" background = "#f59e0b" end
        box: width = 100 height = 70 border top left radius = 40 background = "#f59e0b" display = flex align items = center justify content = center font size = 13 content = "top left" end
        box: width = 100 height = 70 border start end radius = 35 background = "#f59e0b" display = flex align items = center justify content = center font size = 13 content = "start end" end
    end
end

Rounding shapes the background, the border and the shadow, but it does not clip the content. A child that is larger than the box still sticks out of its rounded corner unless the box has overflow = hidden.

Border images

A border does not have to be a line. border image source draws a picture or a gradient in the border area instead. The picture is cut into nine pieces by border image slice: four corners, four edges and a middle. The corners go into the corners of the border as they are, the edges are stretched or repeated along the sides, and the middle is thrown away unless you add fill. This is called a nine-slice frame, and it lets one small picture fit boxes of any size.

The properties that control it are border image slice (how far from each edge of the picture to cut, as a number of the picture's own pixels or a percentage), border image width (how thick the frame is drawn, a length or a multiple of the border width), border image outset (how far it reaches outside the box) and border image repeat (stretch, repeat, round or space). border image is the shorthand for all five, in the order source slice / width / outset repeat. The border itself must still have a width, and a transparent color is the usual choice so that nothing shows through under the picture.

web-border-image.salam
const FRAME := "url('data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2790%27 height=%2790%27%3E%3Crect x=%275%27 y=%275%27 width=%2780%27 height=%2780%27 rx=%2710%27 fill=%27none%27 stroke=%27%230f766e%27 stroke-width=%274%27/%3E%3Ccircle cx=%2715%27 cy=%2715%27 r=%2712%27 fill=%27%23f59e0b%27/%3E%3Ccircle cx=%2775%27 cy=%2715%27 r=%2712%27 fill=%27%23f59e0b%27/%3E%3Ccircle cx=%2715%27 cy=%2775%27 r=%2712%27 fill=%27%23f59e0b%27/%3E%3Ccircle cx=%2775%27 cy=%2775%27 r=%2712%27 fill=%27%23f59e0b%27/%3E%3C/svg%3E')"

page:
    title = "Border image"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        width = 260
        padding = 14
        border = "30px solid transparent"
        border image source = FRAME
        border image slice = 30
        border image width = "30px"
        border image repeat = "round"
        content = "The four corners come from the corners of the picture. The edges are stretched or repeated to fit the box."
    end
end

The frame in the example is a small SVG picture written as a data URL, with an amber circle in each corner. Because the corners are copied and never stretched, the circles stay round on a box of any size, and round repeats the edges a whole number of times so no piece is cut. A gradient works as a source too, and with a slice of 1 it makes the popular gradient border: border image = "linear-gradient(135deg, #f59e0b, #db2777) 1". The one thing a border image cannot do is follow border radius, because the image replaces the line that the radius would have curved.

Outlines and focus rings

outline looks like a border and takes the same width, style and color, but it is different in three ways. It is drawn outside the box and takes no room in the layout, so adding one never moves anything. It can be pushed away from the box with outline offset, or pulled inside with a negative offset. And it is the tool of the browser for showing keyboard focus. The longhands are outline color, outline style (the border styles and also auto, the browser's own ring) and outline width.

Focus is the element that receives the keyboard. A person who cannot use a mouse presses Tab to move from link to button to field, and the focus ring is the only thing that shows where they are. Write the state as a prefix: focus outline = "3px solid #2563eb" applies only while the element has focus. Click into the example and press Tab: the button gets a blue ring set three pixels away, and the input gets a pink one.

web-border-outline.salam
page:
    title = "Outlines and focus rings"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        display = flex gap = 24 flex wrap = wrap align items = center
        button:
            id = "go"
            content = "Tab to me"
            padding = "8px 16px"
            border = "2px solid #0f766e"
            background = "white"
            border radius = 6
            focus outline = "3px solid #2563eb"
            focus outline offset = 3
        end
        input: type = "text" placeholder = "Focus me" padding = 8 focus outline color = "#db2777" focus outline width = 3 focus outline style = solid end
        box: outline = "3px dashed #db2777" outline offset = 6 padding = 12 content = "outline offset 6" end
    end
end

Never write outline = none to get rid of the ring that browsers draw around a focused control, unless you replace it with another clearly visible focus style. Without a ring, a keyboard user cannot tell where they are, and the page fails the accessibility rules that many countries require. The right fix for an ugly ring is a better looking ring, not no ring. The ring should have a contrast ratio of at least 3 to 1 against what is around it.

Box shadows

box shadow draws a shadow behind the box, shaped like its rounded corners. One shadow is written as up to five parts: x y blur spread color. The first two numbers move the shadow right and down (negative numbers move it left and up). Blur softens the edge: 0 is sharp and a bigger number is softer. Spread makes the shadow bigger or, if negative, smaller than the box. The color is almost always a transparent black such as rgb(0 0 0 / 20%), because a shadow lets the page show through. Put inset first and the shadow is drawn inside the box, as if it were pressed in.

Separate several shadows with commas and the first one is on top. A pair of shadows, one close and tight and one far and soft, looks far more natural than a single one, which is how the "layered" card gets its depth. A shadow with no blur and a spread of 4px is a ring that follows the corners, and a blurry shadow with a bright color is a glow.

web-border-shadow.salam
component Card(label, shadow):
    box:
        background = "white"
        width = 120
        height = 80
        display = flex
        align items = center
        justify content = center
        text align = center
        font size = 13
        border radius = 10
        box shadow = shadow
        content = label
    end
end

page:
    title = "Box shadows"
    global: selector = "body" font family = "system-ui, sans-serif" margin = 0 padding = "1.5rem" background = "#e2e8f0" end
    box:
        display = flex gap = 24 flex wrap = wrap
        Card: label = "soft" shadow = "0 4px 12px rgb(0 0 0 / 18%)" end
        Card: label = "hard offset" shadow = "6px 6px 0 #0f172a" end
        Card: label = "spread ring" shadow = "0 0 0 4px #60a5fa" end
        Card: label = "inset" shadow = "inset 0 3px 8px rgb(0 0 0 / 30%)" end
        Card: label = "glow" shadow = "0 0 24px #22d3ee" end
        Card: label = "layered" shadow = "0 1px 2px rgb(0 0 0 / 20%), 0 8px 24px rgb(0 0 0 / 18%)" end
    end
end

The next example lets you try the values. The sliders write a new box-shadow and border-radius to the card and print the CSS they made, so you can read how each number changes the look.

web-border-play.salam
import dom

func update():
    x := dom.GetValue(dom.ById("x"))
    y := dom.GetValue(dom.ById("y"))
    blur := dom.GetValue(dom.ById("blur"))
    radius := dom.GetValue(dom.ById("radius"))
    shadow := x + "px " + y + "px " + blur + "px rgb(0 0 0 / 35%)"
    dom.SetStyle(dom.ById("card"), "box-shadow", shadow)
    dom.SetStyle(dom.ById("card"), "border-radius", radius + "px")
    dom.SetText(dom.ById("css"), "box-shadow: " + shadow + "; border-radius: " + radius + "px")
end

page:
    title = "Shadow lab"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box: id = "card" width = 180 height = 90 margin = "10px 0 20px" background = "white" border = "1px solid #cbd5e1" box shadow = "0px 4px 12px rgb(0 0 0 / 35%)" border radius = 12 end
    box: label: content = "x" width = 60 display = "inline-block" end input: type = "range" id = "x" min = "-20" max = "20" value = "0" input = update end end
    box: label: content = "y" width = 60 display = "inline-block" end input: type = "range" id = "y" min = "-20" max = "20" value = "4" input = update end end
    box: label: content = "blur" width = 60 display = "inline-block" end input: type = "range" id = "blur" min = "0" max = "40" value = "12" input = update end end
    box: label: content = "radius" width = 60 display = "inline-block" end input: type = "range" id = "radius" min = "0" max = "45" value = "12" input = update end end
    paragraph: id = "css" content = "box-shadow: 0px 4px 12px rgb(0 0 0 / 35%); border-radius: 12px" end
end

A shadow is only decoration and never changes the layout, so it can overlap the neighbours and it can be cut by a parent with overflow = hidden. For text use text shadow, and for the shape of an image with transparent parts use the drop-shadow() filter from the previous lesson.

Broken boxes and new corner shapes

An inline element such as a span can wrap onto several lines, and then its padding, border and background have to be drawn on more than one piece. box decoration break chooses how. With slice, the default, the element is drawn as if it were one long box that has been cut with scissors, so the left edge appears only on the first piece and the right edge only on the last. With clone every piece is a complete box with its own edges, padding and corners. Use clone for highlights and tags that may wrap.

web-border-break.salam
page:
    title = "Box decoration break"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" max width = "280px" line height = 2.2 end
    paragraph:
        content = "Slice (the default): "
        span: background = "#fde68a" padding = "2px 10px" border radius = 8 border = "2px solid #b45309" box decoration break = "slice" content = "one highlight cut into pieces where the line breaks" end
    end
    paragraph:
        content = "Clone: "
        span: background = "#fde68a" padding = "2px 10px" border radius = 8 border = "2px solid #b45309" box decoration break = "clone" content = "every piece gets its own padding, border and corners" end
    end
end

The corner shape properties change what a rounded corner looks like. Until now the curve was always a quarter circle. corner shape can make it a squircle (a softer, superelliptical curve, like app icons), a bevel (cut straight across), a scoop (curved inward) or a notch (a square cut inward), and each corner has its own property, such as corner top left shape. The shape is applied to the corners that border radius sets, so the radius is still needed to say how large the corner is.

web-border-corners.salam
component Tile(label, shape):
    box:
        width = 100
        height = 80
        background = "#7c3aed"
        color = "white"
        display = flex
        align items = center
        justify content = center
        border radius = 28
        font size = 13
        corner shape = shape
        content = label
    end
end

page:
    title = "Corner shapes"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    box:
        display = flex gap = 16 flex wrap = wrap
        Tile: label = "round" shape = "round" end
        Tile: label = "squircle" shape = "squircle" end
        Tile: label = "bevel" shape = "bevel" end
        Tile: label = "scoop" shape = "scoop" end
        Tile: label = "notch" shape = "notch" end
        Tile: label = "scoop bevel" shape = "scoop bevel" end
    end
end

Corner shapes are new and so far only Chromium browsers draw them. In other browsers the corners simply stay round, which is a fine fallback because the box still works. Do not make a design depend on them yet. Borders in tables, with border collapse, are covered in the lesson on more properties.

How the compiler checks values

Every style value in a page is checked while the page is compiled, not in the browser. A browser silently ignores a CSS value it does not understand, and the page just looks wrong with no message. In Salam a bad value stops the build with error E018. The message names the property, shows the value you wrote and says what was expected. For example, writing a style of wobbly in border style reports invalid value for 'border style': 'wobbly' is not 'none', 'hidden', 'dotted', ... followed by the file, line and column where the value is. A radius of big reports that it is not a length or a percentage, and a border shorthand with parts that do not belong together says that it is not a valid combination for this property.

The check works on the shorthands as well. It splits border into its parts and checks each part against its own rules, so a typo in a color name inside "2px solid reed" is found too. Persian files accept the Persian value names such as یکپارچه and خط‌چین in the same places, and the messages are in Persian. The tables below show the values each property accepts.

Reference: borders, outlines and shadows

Every property of this lesson is listed below. Each one has a one-line description of what it accepts and an example that the compiler has checked. The groups follow the lesson: the shorthand and the four values rule, the four physical sides, the logical sides, the corners, the border image, and then outline, shadow and the corner shapes.

All sides

PropertyWhat it does and what it acceptsExample
border
کادر
border
Draws a border on all four sides. The value is a width, a style and a color in any order, for example 2px solid #0f766e. The style is required, because the default none shows nothing. [CSS-wide keywords only]box: padding = 12 border = "2px solid #0f766e" content = "border" end
border width
ضخامت کادر
border-width
The thickness of the borders, with the same one to four value rules as border color. Each value is a length, or thin, medium or thick. [length / thin, medium, thick; up to 4 values]box: padding = 12 border style = solid border color = "#0f766e" border width = "1px 4px 8px 12px" content = "1, 4, 8, 12" end
border style
سبک کادر
border-style
The line style of the borders, with the same one to four value rules as border color. The values are none, hidden, dotted, dashed, solid, double, groove, ridge, inset and outset. [none, hidden, dotted, dashed, solid, double, ...; up to 4 values]box: padding = 12 border = "6px solid #7c3aed" border style = "solid dashed" content = "solid, dashed" end
border color
رنگ کادر
border-color
The color of the borders. One value colors all four sides; two values are top and bottom then left and right; three are top, left and right, bottom; four go clockwise from the top. [color; up to 4 values]box: padding = 12 border = "8px solid black" border color = "#ef4444 #22c55e #3b82f6 #eab308" content = "four colors" end

Top

PropertyWhat it does and what it acceptsExample
border top
کادر بالا
border-top
Sets the width, style and color of the top border in one value, such as 3px solid #0f766e. A part you leave out gets its default, and the style must be present because the default style none draws nothing. [CSS-wide keywords only]box: padding = 12 border top = "3px solid #0f766e" content = "top border" end
border top width
ضخامت کادر بالا
border-top-width
The thickness of the top border: a length such as 4px, or thin, medium or thick. It has no effect while the style is none. [length / thin, medium, thick]box: padding = 12 border = "1px solid #0f766e" border top width = 8 content = "top 8px" end
border top style
سبک کادر بالا
border-top-style
The line style of the top border: none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. With no style, nothing is drawn. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #0f766e" border top style = dashed content = "top dashed" end
border top color
رنگ کادر بالا
border-top-color
The color of the top border only. It takes any color. Without it the border uses the text color of the element. [color]box: padding = 12 border = "4px solid #cbd5e1" border top color = "#db2777" content = "top color" end

Right

PropertyWhat it does and what it acceptsExample
border right
کادر راست
border-right
Sets the width, style and color of the right border in one value, such as 5px solid #dc2626. A part you leave out gets its default, and the style must be present because the default style none draws nothing. [CSS-wide keywords only]box: padding = 12 border right = "5px solid #dc2626" content = "right border" end
border right width
ضخامت کادر راست
border-right-width
The thickness of the right border: a length such as 4px, or thin, medium or thick. It has no effect while the style is none. [length / thin, medium, thick]box: padding = 12 border = "1px solid #dc2626" border right width = 11 content = "right 11px" end
border right style
سبک کادر راست
border-right-style
The line style of the right border: none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. With no style, nothing is drawn. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #dc2626" border right style = dotted content = "right dotted" end
border right color
رنگ کادر راست
border-right-color
The color of the right border only. It takes any color. Without it the border uses the text color of the element. [color]box: padding = 12 border = "4px solid #cbd5e1" border right color = "#ca8a04" content = "right color" end

Bottom

PropertyWhat it does and what it acceptsExample
border bottom
کادر پایین
border-bottom
Sets the width, style and color of the bottom border in one value, such as 7px solid #2563eb. A part you leave out gets its default, and the style must be present because the default style none draws nothing. [CSS-wide keywords only]box: padding = 12 border bottom = "7px solid #2563eb" content = "bottom border" end
border bottom width
ضخامت کادر پایین
border-bottom-width
The thickness of the bottom border: a length such as 4px, or thin, medium or thick. It has no effect while the style is none. [length / thin, medium, thick]box: padding = 12 border = "1px solid #2563eb" border bottom width = 14 content = "bottom 14px" end
border bottom style
سبک کادر پایین
border-bottom-style
The line style of the bottom border: none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. With no style, nothing is drawn. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #2563eb" border bottom style = double content = "bottom double" end
border bottom color
رنگ کادر پایین
border-bottom-color
The color of the bottom border only. It takes any color. Without it the border uses the text color of the element. [color]box: padding = 12 border = "4px solid #cbd5e1" border bottom color = "#7c3aed" content = "bottom color" end

Left

PropertyWhat it does and what it acceptsExample
border left
کادر چپ
border-left
Sets the width, style and color of the left border in one value, such as 9px solid #db2777. A part you leave out gets its default, and the style must be present because the default style none draws nothing. [CSS-wide keywords only]box: padding = 12 border left = "9px solid #db2777" content = "left border" end
border left width
ضخامت کادر چپ
border-left-width
The thickness of the left border: a length such as 4px, or thin, medium or thick. It has no effect while the style is none. [length / thin, medium, thick]box: padding = 12 border = "1px solid #db2777" border left width = 17 content = "left 17px" end
border left style
سبک کادر چپ
border-left-style
The line style of the left border: none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. With no style, nothing is drawn. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #db2777" border left style = groove content = "left groove" end
border left color
رنگ کادر چپ
border-left-color
The color of the left border only. It takes any color. Without it the border uses the text color of the element. [color]box: padding = 12 border = "4px solid #cbd5e1" border left color = "#ea580c" content = "left color" end

Block sides

PropertyWhat it does and what it acceptsExample
border block
کادر بلوکی
border-block
Sets the border on both block sides at once, which are the top and the bottom in horizontal text. It takes the same width, style and color as border. [CSS-wide keywords only]box: padding = 12 border block = "3px solid #0f766e" content = "block: top and bottom" end
border block width
ضخامت کادر بلوکی
border-block-width
The thickness of the two block borders. One value sets both; two values give the start and then the end. [length / thin, medium, thick; up to 2 values]box: padding = 12 border = "1px solid #7c3aed" border block width = "2px 10px" content = "thin above, thick below" end
border block style
سبک کادر بلوکی
border-block-style
The line style of the two block borders. One value styles both; two values give the start and then the end. [none, hidden, dotted, dashed, solid, double, ...; up to 2 values]box: padding = 12 border = "5px solid #0f766e" border block style = "dashed double" content = "dashed above, double below" end
border block color
رنگ کادر بلوکی
border-block-color
The color of the two block borders. One value colors both; two values give the start and then the end. [color; up to 2 values]box: padding = 12 border = "5px solid #e2e8f0" border block color = "#dc2626 #2563eb" content = "start red, end blue" end
border block start
کادر بلوکی آغاز
border-block-start
Sets the width, style and color of the border at the start of the block direction (the top in horizontal text) in one value. It follows the writing direction, so the same code works in left to right and right to left pages. [CSS-wide keywords only]box: padding = 12 border block start = "4px solid #7c3aed" content = "block-start" end
border block start width
ضخامت کادر بلوکی آغاز
border-block-start-width
The thickness of the border at the start of the block direction (the top in horizontal text): a length, or thin, medium or thick. [length / thin, medium, thick]box: padding = 12 border = "1px solid #7c3aed" border block start width = 9 content = "block-start 9px" end
border block start style
سبک کادر بلوکی آغاز
border-block-start-style
The line style of the border at the start of the block direction (the top in horizontal text): none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #7c3aed" border block start style = dashed content = "block-start dashed" end
border block start color
رنگ کادر بلوکی آغاز
border-block-start-color
The color of the border at the start of the block direction (the top in horizontal text). It takes any color. [color]box: padding = 12 border = "4px solid #e2e8f0" border block start color = "#16a34a" content = "block-start color" end
border block end
کادر بلوکی انتها
border-block-end
Sets the width, style and color of the border at the end of the block direction (the bottom in horizontal text) in one value. It follows the writing direction, so the same code works in left to right and right to left pages. [CSS-wide keywords only]box: padding = 12 border block end = "6px solid #ea580c" content = "block-end" end
border block end width
ضخامت کادر بلوکی انتها
border-block-end-width
The thickness of the border at the end of the block direction (the bottom in horizontal text): a length, or thin, medium or thick. [length / thin, medium, thick]box: padding = 12 border = "1px solid #ea580c" border block end width = 11 content = "block-end 11px" end
border block end style
سبک کادر بلوکی انتها
border-block-end-style
The line style of the border at the end of the block direction (the bottom in horizontal text): none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #ea580c" border block end style = dotted content = "block-end dotted" end
border block end color
رنگ کادر بلوکی انتها
border-block-end-color
The color of the border at the end of the block direction (the bottom in horizontal text). It takes any color. [color]box: padding = 12 border = "4px solid #e2e8f0" border block end color = "#be123c" content = "block-end color" end

Inline sides

PropertyWhat it does and what it acceptsExample
border inline
کادر خطی
border-inline
Sets the border on both inline sides at once, which are the left and the right in horizontal text. It takes the same width, style and color as border. [CSS-wide keywords only]box: padding = 12 border inline = "4px dotted #ea580c" content = "inline: left and right" end
border inline width
ضخامت کادر خطی
border-inline-width
The thickness of the two inline borders. One value sets both; two values give the start and then the end. [length / thin, medium, thick; up to 2 values]box: padding = 12 border = "1px solid #be123c" border inline width = "12px 2px" content = "thick start, thin end" end
border inline style
سبک کادر خطی
border-inline-style
The line style of the two inline borders. One value styles both; two values give the start and then the end. [none, hidden, dotted, dashed, solid, double, ...; up to 2 values]box: padding = 12 border = "5px solid #0891b2" border inline style = "solid dotted" content = "solid start, dotted end" end
border inline color
رنگ کادر خطی
border-inline-color
The color of the two inline borders. One value colors both; two values give the start and then the end. [color; up to 2 values]box: padding = 12 border = "5px solid #e2e8f0" border inline color = "#16a34a #ca8a04" content = "start green, end yellow" end
border inline start
کادر خطی آغاز
border-inline-start
Sets the width, style and color of the border at the side where a line of text starts (left in English, right in Persian) in one value. It follows the writing direction, so the same code works in left to right and right to left pages. [CSS-wide keywords only]box: padding = 12 border inline start = "8px solid #0891b2" content = "inline-start" end
border inline start width
ضخامت کادر خطی آغاز
border-inline-start-width
The thickness of the border at the side where a line of text starts (left in English, right in Persian): a length, or thin, medium or thick. [length / thin, medium, thick]box: padding = 12 border = "1px solid #0891b2" border inline start width = 13 content = "inline-start 13px" end
border inline start style
سبک کادر خطی آغاز
border-inline-start-style
The line style of the border at the side where a line of text starts (left in English, right in Persian): none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #0891b2" border inline start style = double content = "inline-start double" end
border inline start color
رنگ کادر خطی آغاز
border-inline-start-color
The color of the border at the side where a line of text starts (left in English, right in Persian). It takes any color. [color]box: padding = 12 border = "4px solid #e2e8f0" border inline start color = "#4f46e5" content = "inline-start color" end
border inline end
کادر خطی انتها
border-inline-end
Sets the width, style and color of the border at the side where a line of text ends (right in English, left in Persian) in one value. It follows the writing direction, so the same code works in left to right and right to left pages. [CSS-wide keywords only]box: padding = 12 border inline end = "10px solid #16a34a" content = "inline-end" end
border inline end width
ضخامت کادر خطی انتها
border-inline-end-width
The thickness of the border at the side where a line of text ends (right in English, left in Persian): a length, or thin, medium or thick. [length / thin, medium, thick]box: padding = 12 border = "1px solid #16a34a" border inline end width = 15 content = "inline-end 15px" end
border inline end style
سبک کادر خطی انتها
border-inline-end-style
The line style of the border at the side where a line of text ends (right in English, left in Persian): none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. [none, hidden, dotted, dashed, solid, double, ...]box: padding = 12 border = "6px solid #16a34a" border inline end style = ridge content = "inline-end ridge" end
border inline end color
رنگ کادر خطی انتها
border-inline-end-color
The color of the border at the side where a line of text ends (right in English, left in Persian). It takes any color. [color]box: padding = 12 border = "4px solid #e2e8f0" border inline end color = "#0d9488" content = "inline-end color" end

Corners

PropertyWhat it does and what it acceptsExample
border radius
گردی کادر
border-radius
Rounds the corners. One value rounds all four; two values are top left with bottom right, then top right with bottom left; four go clockwise from the top left. A / gives separate horizontal and vertical radii for oval corners, and 50% on a square makes a circle. [length / percentage; up to 4 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border radius = "24px 4px" content = "24px 4px" end
border top left radius
گردی کادر بالا چپ
border-top-left-radius
Rounds only the top left corner. One value makes it circular; two values (40px 20px) make an oval with a horizontal and then a vertical radius. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border top left radius = "40px 20px" content = "top left 40px 20px" end
border top right radius
گردی کادر بالا راست
border-top-right-radius
Rounds only the top right corner. One value makes it circular; two values (40px 20px) make an oval with a horizontal and then a vertical radius. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border top right radius = 30 content = "top right 30" end
border bottom left radius
گردی کادر پایین چپ
border-bottom-left-radius
Rounds only the bottom left corner. One value makes it circular; two values (40px 20px) make an oval with a horizontal and then a vertical radius. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border bottom left radius = "50%" content = "bottom left 50%" end
border bottom right radius
گردی کادر پایین راست
border-bottom-right-radius
Rounds only the bottom right corner. One value makes it circular; two values (40px 20px) make an oval with a horizontal and then a vertical radius. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border bottom right radius = "60px 10px" content = "bottom right 60px 10px" end
border start start radius
گردی کادر آغاز آغاز
border-start-start-radius
Rounds the corner at the start of the block side at the start of the inline side (top left in English, top right in Persian). It follows the writing direction, like the other logical properties. One or two values, as for the physical corners. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border start start radius = 28 content = "start-start" end
border start end radius
گردی کادر آغاز انتها
border-start-end-radius
Rounds the corner at the block start with the inline end (top right in English, top left in Persian). It follows the writing direction, like the other logical properties. One or two values, as for the physical corners. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border start end radius = "36px 12px" content = "start-end" end
border end start radius
گردی کادر انتها آغاز
border-end-start-radius
Rounds the corner at the block end with the inline start (bottom left in English, bottom right in Persian). It follows the writing direction, like the other logical properties. One or two values, as for the physical corners. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border end start radius = "50%" content = "end-start" end
border end end radius
گردی کادر انتها انتها
border-end-end-radius
Rounds the corner at the block end with the inline end (bottom right in English, bottom left in Persian). It follows the writing direction, like the other logical properties. One or two values, as for the physical corners. [length / percentage; up to 2 values]box: width = 120 height = 70 padding = 8 background = "#bae6fd" border end end radius = 40 content = "end-end" end

Border image

PropertyWhat it does and what it acceptsExample
border image
تصویر کادر
border-image
The shorthand for the border image: a source, then a slice, then the width and outset after /, then the repeat, for example linear-gradient(#f59e0b, #db2777) 1 / 8px. The border itself must have a width, and a transparent color lets the image show. [CSS-wide keywords only]box: padding = 12 border = "14px solid transparent" border image = "linear-gradient(135deg, #f59e0b, #db2777) 1" content = "gradient frame" end
border image source
منبع تصویر کادر
border-image-source
The image drawn as the border: a url(...) (a data URL works too), a gradient, or none. [image]box: padding = 12 border = "14px solid transparent" border image source = "linear-gradient(90deg, #22d3ee, #6366f1)" border image slice = 1 content = "image source" end
border image slice
برش تصویر کادر
border-image-slice
Where the image is cut into nine parts: up to four numbers or percentages measured from the top, right, bottom and left edges of the image. The corners are used as they are and the edges are repeated or stretched. The word fill keeps the middle part too. [number / percentage; up to 5 values]box: padding = 12 border = "14px solid transparent" border image source = "repeating-linear-gradient(45deg, #0f766e 0 6px, #99f6e4 6px 12px)" border image slice = 2 content = "slice 2" end
border image width
ضخامت تصویر کادر
border-image-width
The size of the area the image is drawn into, one to four values: a length, a percentage of the box, or a plain number that multiplies the border width. The default is 1. [length / percentage / number; up to 4 values]box: padding = 12 border = "14px solid transparent" border image source = "linear-gradient(#f43f5e, #f59e0b)" border image slice = 1 border image width = 2 content = "twice the border width" end
border image outset
بیرون‌زدگی تصویر کادر
border-image-outset
How far the image is pushed outward past the border box, one to four values as a length or a plain number of border widths. It does not take any room in the layout. [length / number; up to 4 values]box: margin = 16 padding = 12 border = "14px solid transparent" border image source = "linear-gradient(135deg, #16a34a, #0891b2)" border image slice = 1 border image outset = 8 content = "pushed out 8px" end
border image repeat
تکرار تصویر کادر
border-image-repeat
How the edge pieces fill their sides, one value for both directions or two (horizontal, vertical): stretch (the default), repeat, round (repeat, resized to fit a whole number of times) and space (repeat with gaps). [up to 2 values]box: padding = 12 border = "14px solid transparent" border image source = "repeating-linear-gradient(90deg, #7c3aed 0 10px, #ddd6fe 10px 20px)" border image slice = 1 border image repeat = round content = "round" end

Outline

PropertyWhat it does and what it acceptsExample
outline
دورخط
outline
Draws a line around the outside of the element, in the same width style color form as border. It takes no room in the layout and can follow rounded corners in current browsers. Focus rings are outlines. [CSS-wide keywords only]box: padding = 12 outline = "3px solid #2563eb" content = "outline" end
outline width
ضخامت دورخط
outline-width
The thickness of the outline: a length, or thin, medium or thick. It has no effect while the style is none. [length / thin, medium, thick]box: padding = 12 outline style = solid outline color = "#ea580c" outline width = 6 content = "6px outline" end
outline style
سبک دورخط
outline-style
The line style of the outline: the same values as border styles, and also auto, which asks the browser for its own native focus ring. [auto, none, hidden, dotted, dashed, solid, ...]box: padding = 12 outline style = dotted outline width = 3 outline color = "#7c3aed" content = "dotted outline" end
outline color
رنگ دورخط
outline-color
The color of the outline. It takes any color. Keep a focus outline easy to see against both the element and the page behind it. [color]box: padding = 12 outline style = solid outline width = 3 outline color = "#db2777" content = "pink outline" end
outline offset
فاصله دورخط
outline-offset
The gap between the outline and the edge of the border box, as a length. A positive value moves the outline away, a negative one pulls it inside. The default is 0. [length]box: padding = 12 margin = 10 outline = "2px dashed #0f766e" outline offset = 8 content = "8px away" end

Shadow, breaks and corner shapes

PropertyWhat it does and what it acceptsExample
box decoration break
شکستن تزیین جعبه
box-decoration-break
What happens to the padding, border and background of an element that breaks across lines or columns. slice (the default) cuts one piece into parts and clone gives every part its own full decoration. [slice, clone]paragraph: width = 180 content = "A " span: box decoration break = clone background = "#fde68a" padding = "0 8px" border radius = 6 content = "highlight that wraps over two lines" end end
box shadow
سایه کادر
box-shadow
Draws one or more shadows around the box. Each shadow is x y blur spread color: the horizontal and vertical offset, how soft the edge is, how much larger or smaller it is, and its color. The word inset draws it inside. Separate several shadows with commas; the first is on top. [comma list]box: padding = 16 border radius = 10 box shadow = "0 6px 16px rgb(0 0 0 / 20%), inset 0 0 0 1px #cbd5e1" content = "two shadows" end
corner shape
شکل گوشه
corner-shape
Changes the shape of the corners that border radius rounds, one to four values: round (the default), squircle, bevel, scoop, notch, square or superellipse(). It is new and works only in Chromium browsers for now; elsewhere the corners stay round. [up to 4 of round, scoop, bevel, notch, square, squircle, superellipse()]box: padding = 16 border radius = 24 corner shape = "squircle" background = "#0ea5e9" color = "white" content = "squircle" end
corner top left shape
شکل گوشه بالا چپ
corner-top-left-shape
The shape of the top left corner only: round, squircle, bevel, scoop, notch, square or superellipse(). It needs a border radius to show, and only Chromium browsers draw it for now. [a corner shape keyword or superellipse()]box: padding = 16 border radius = 28 corner top left shape = scoop background = "#ea580c" color = "white" content = "top left: scoop" end
corner top right shape
شکل گوشه بالا راست
corner-top-right-shape
The shape of the top right corner only: round, squircle, bevel, scoop, notch, square or superellipse(). It needs a border radius to show, and only Chromium browsers draw it for now. [a corner shape keyword or superellipse()]box: padding = 16 border radius = 28 corner top right shape = bevel background = "#16a34a" color = "white" content = "top right: bevel" end
corner bottom left shape
شکل گوشه پایین چپ
corner-bottom-left-shape
The shape of the bottom left corner only: round, squircle, bevel, scoop, notch, square or superellipse(). It needs a border radius to show, and only Chromium browsers draw it for now. [a corner shape keyword or superellipse()]box: padding = 16 border radius = 28 corner bottom left shape = notch background = "#7c3aed" color = "white" content = "bottom left: notch" end
corner bottom right shape
شکل گوشه پایین راست
corner-bottom-right-shape
The shape of the bottom right corner only: round, squircle, bevel, scoop, notch, square or superellipse(). It needs a border radius to show, and only Chromium browsers draw it for now. [a corner shape keyword or superellipse()]box: padding = 16 border radius = 28 corner bottom right shape = squircle background = "#db2777" color = "white" content = "bottom right: squircle" end

Try it yourself

  • Make a notification box with a thick border inline start in red, then put it inside a box with dir = "rtl" and check that the stripe moves to the right by itself.
  • Build a button with a pill shape, a box shadow that gets smaller on active, and a focus ring of a different color.
  • Make a gradient border with border image and a slice of 1, and try to round its corners. What happens, and what can you use instead?
  • Add a fourth slider to the shadow lab that changes the spread, and a checkbox that adds the word inset.