Skip to main navigation Skip to main content Skip to page footer

KKS-14 — Gradient background with vector

The decorative shape is a stackable modifier, not a background of its own. It lives on tt_content.frame_options as the value vector and renders as .frame-option-vector, so it can be ticked on top of whichever gradient the editor picked — Appearance → Frame Options → »Decorative vector (circle shape, left edge)«.

Figma source: artboard KKS-Netzwerk-Startseite, panel Rectangle 3 (node 409-10539, 1280×836, fill Verlauf) with Subtract on top (node 409-10540, 746×746 at Left −209, fill Orange #F55E21).

Check the rendered values in the console:

var f = document.querySelector('.frame-option-vector'), s = getComputedStyle(f, '::before');
s.backgroundSize + ' | ' + s.backgroundPosition   // expect "41.953% auto | left center"

Wissen gestalten. Orientierung geben.

Warm gradient (Verlauf, gradientwarm) with the vector ticked — the panel from the Startseite artboard. The shape bleeds 209px off the left page edge, so only 537 of its 746px are visible, and it is centred vertically.

Sizing is by frame width (537 / 1280 = 41.953 %), not frame height, so the proportion holds at every viewport instead of growing on tall content. Resize the window and the shape scales with the page rather than with this paragraph.

Running text belongs on the left, at the dark red end of the ramp. Note the shape carries a concentric circular hole, so text set over its middle still reads against the gradient rather than against flat orange.

This panel is padded out to roughly 836px tall on purpose — that is the height of Rectangle 3 in Figma, and at 1280px wide it is the one height at which the rendering should be pixel-comparable to the artboard. The artwork is 746px of that 836, i.e. 44px clear at the top and 46px at the bottom, which is vertical centring to within a pixel.

Below that height the fixed 537:746 ratio means the rounded ends fall outside the box — see the short frame further down, which is there to make the limit visible rather than to hide it. Above it the shape simply sits centred with more gradient showing above and below, because it is sized off the width and does not stretch.

The concentric hole is the part worth checking against Figma: it is a true circle of radius 179.593 centred at (164, 373) in the artwork’s own coordinates, with quarter-circle notches cut at x = 164 top and bottom. If the shape ever renders as a plain rounded square, the fill-rule on the single-path geometry has been lost somewhere in the data URI.

One more thing to look at: the shape is #F55E21 at full opacity sitting on a ramp that runs #E23025#EE5027#EE9427. It is meant to read as a subtle tonal shift, not as a separate object — brighter than the gradient at the left end and almost invisible where the ramp catches up with it.

Same gradient, vector off

The control case, and the reason this is a modifier rather than two more background options: Figma uses the warm gradient plain as well — the hero on KKS-Netzwerk-Vernetzung und Kooperation has no vector. Anything that made the shape automatic on gradientwarm would break that page.

Cool gradient — composes for free

The same tick on gradientcool (Verlauf 2, navy → petrol → mint). Figma only draws the vector on the warm panel, but because the option is orthogonal to the background it costs nothing to support here — and one CSS rule covers both, where two extra $frame-backgrounds entries would have multiplied out across the 14 files that loop over that map.

Keep body copy at the navy end: KKS-17 recorded that the mint stop #54C9BE is only 2.0:1 against white.

Worth judging deliberately rather than accepting by default: the shape keeps its orange $tertiary fill here, because that is the token Figma uses and nothing in the design says the decoration recolours per gradient. On the warm ramp that reads as a tonal shift; on this cool ramp it reads as a distinct orange object against navy, which is a much louder effect.

If the design intent turns out to be “a tonal shift, whatever the background”, the fix belongs in $frame-backgrounds as a per-variant decoration colour rather than in the option — the option would then read its fill from the frame instead of hardcoding one token. That is a design decision, so it is flagged here rather than guessed at.

This panel is padded to clear 746px so the full silhouette is visible for that comparison, including the rounded ends and the concentric hole.

Two details to check while the whole shape is on screen. First, the quarter-circle notches: the artwork is a single path, and the notches at x = 164 are what make it read as an interlocking form rather than a circle inside a square. Second, the left crop: the visible edge at x = 0 is a straight vertical cut, not a curve — if it ever looks curved, the viewBox has been widened and the 209px bleed lost.

The gradient underneath is unchanged from KKS-17: $primary 0 % → $secondary-700 49 % → $secondary 100 %, all three stops present. The middle stop carries the character of the ramp and must never be dropped.

Stacking — vector plus a ruler

frame_options is a checkbox list, so values stack. Here it holds ruler-before,vector: bootstrap-package’s own option and the new one on the same element. The item was appended with addTcaSelectItem() rather than the column being re-declared, which is what keeps the four inherited options alive.

This is the case that decided the class prefix. A core content element ends up with both frame-vector (from the layout’s headerClass string) and frame-option-vector (from FrameViewHelper), but the Mask templates that assemble their own class list only ever emit frame-option-. Styling that one means the option behaves identically on a text element and on a Mask element — the inconsistency KKS-16 flagged, avoided rather than inherited.

Check it in the console: document.querySelector('.frame-option-vector').className shows both prefixes present, and only the frame-option- one carries a rule.

Padded to clear 746px as well, so the ruler above and the full shape can be seen at the same time.

The ruler is bootstrap-package’s ruler-before, drawn above this frame by its own rule; the vector is painted by a ::before on the frame itself. They do not know about each other, which is the point of a checkbox list — an editor can combine any subset and each option contributes independently.

The one combination that does not compose is frame_class = 2frame, because it repaints --frame-background onto .frame-group-container with the background shorthand and so overwrites the decoration. That is a different frame appearance rather than a modifier, so the two were never meant to stack.

Stacking order is worth one glance too: the decoration sits at z-index: 0 and the content wrapper is lifted to 1. Without that lift an absolutely positioned pseudo-element would paint over the text, because positioned boxes come after in-flow content in the paint order.

Known limit — a short frame clips the ends

One line of content.

Why the frame above looks cropped

The artwork has a fixed 537:746 ratio and is sized off the frame width, so on a frame shorter than 58.28 % of its own width the rounded top and bottom fall outside the box. Unavoidable for a fixed-ratio background layer, and Figma’s own panel is 836px tall — well clear of the threshold. Recorded rather than silently accepted.

Also known: frame_class = 2frame paints the gradient onto .frame-group-container with the background shorthand, which overwrites the decoration. Those two are different appearances and are not meant to stack.

Datenschutz Einstellungen
KKSN KKSN