Navigation

v0.0.4
Media

Window

The frame of an application around a screenshot, a demo or a terminal.

On this page

A window is the frame of an application drawn around something you want to show: a screenshot, a short demo, a few lines of a terminal. It is a lifted sheet with a bar across its top. The three marks in the bar are drawn in the ink of a line, with no hue, so the frame says "this is a window" and leaves the color to what it holds.

Window

<figure class="window max-w(520) mx-auto">  <div class="window-bar">    <span class="window-controls" aria-hidden="true"></span>    <span class="window-title">Atlas · Deployments</span>  </div>  <img class="window-body object-cover w-full" style="aspect-ratio: 16 / 10" src="/demo/moonstone.svg" alt="The deployments view of Atlas"></figure>

#The bar

window-bar has three places. window-controls stands at the start: one empty element, drawn as three discs. In the middle goes a window-title, or a window-address, a small well like a browser's. window-end holds anything that belongs at the far end. Each part is optional, and the middle stays centered whatever stands beside it.

An address

<figure class="window max-w(520) mx-auto">  <div class="window-bar">    <span class="window-controls" aria-hidden="true"></span>    <span class="window-address">      <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">        <path d="M8 11V8a4 4 0 0 1 8 0v3M6 11h12v9H6z" />      </svg>atlas.dev/deployments</span>    <span class="window-end">      <span class="badge badge-sm badge-success badge-dot">Live</span>    </span>  </div>  <div class="window-body flex flex-col gap-sm p-lg">    <div class="skeleton skeleton-text w(180)"></div>    <div class="skeleton skeleton-text"></div>    <div class="skeleton skeleton-text w(320)"></div>    <div class="skeleton h(96) mt-xs"></div>  </div></figure>

#The body

window-body has no padding, so a picture or a video meets the frame, and the window's own corner cuts it; give text its room with a padding utility. Put the class on the element that is the content: an <img>, a <video>, a <pre> or a <div>.

window-flat keeps one contour and drops the shadow, for a window on a tray or among other things on a dense page.

A terminal

<figure class="window window-flat max-w(520) mx-auto">  <div class="window-bar">    <span class="window-controls" aria-hidden="true"></span>    <span class="window-title">zsh</span>  </div><pre class="window-body p-md font-mono text-xs leading-lg fg-text-strong overflow-x-auto"><span class="fg-text-muted">$</span> npm install @master/css @master/ui<span class="fg-text-muted">added 2 packages in 1.4s</span><span class="fg-text-muted">$</span> npm run dev</pre></figure>

#Accessibility

  • The frame is decoration. Hide window-controls with aria-hidden="true": the discs are not buttons and do nothing.
  • A <figure> suits a window that illustrates the text around it; add a <figcaption> after it when the picture needs explaining.
  • Describe a screenshot in its alt. The title in the bar is part of the picture, not a replacement for that description.
  • Do not build a working dialog from this. A window that opens over the page is a dialog.

#Classes

ClassDescription
windowThe frame: a lifted sheet with a 12px corner that clips what it holds
window-flatOne contour and no shadow, for a window on a tray or in a dense page. With window
window-barThe bar across the top: marks at the start, a title or an address in the middle, room for a control at the end
window-controlsThree marks at the start of the bar, drawn from one empty element; hide it with aria-hidden="true"
window-titleA title in the middle of the bar, on one line
window-addressAn address in a small well in the middle of the bar, instead of a title
window-endWhat stands at the end of the bar
window-bodyWhat the window shows: an image, a video, a pre or a div. It has no padding

#Custom properties

PropertyDefaultDescription
--window-radiusvar(--radius-control-lg)Corner of the frame
--window-bar-height2.5remHeight of the bar

#Source

@master/ui/components/window.css
/* * Window: the frame of an application around a screenshot, a demo or a few lines of a terminal. * A lifted sheet with a 12px corner. Its bar is a quieter tone over a hairline and carries three marks at * the start, drawn from one element in the ink of a line, with no hue: the frame says "this is a window" * and leaves the color to what it shows. A title stands in the middle of the bar, or an address in a small * well. The body is cut by the window's own corner, so a picture runs to the edge. */@layer components {  .window {    --window-radius: var(--radius-control-lg);    --window-bar-height: 2.5rem;    --surface-color: var(--color-surface-raised);    position: relative;    display: flex;    flex-direction: column;    min-width: 0;    margin: 0;    border-radius: calc(var(--window-radius) * var(--corner-scale));    corner-shape: var(--corner-shape);    /* The bar's tone and a picture in the body are finished by the window's corner. */    overflow: clip;    background: var(--color-surface-raised);    color: var(--color-text-body);    box-shadow: var(--shadow-lifted);    /* One contour and no lift, for a window on a tray or in a dense page. */    &.window-flat {      box-shadow: var(--shadow-flat);    }    @media (forced-colors: active) {      outline: 1px solid CanvasText;      outline-offset: -1px;    }  }  /* The bar: the marks at the start, the title or the address in the middle, and room for a control at the end. */  .window-bar {    display: grid;    flex: none;    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);    align-items: center;    gap: .75rem;    min-height: var(--window-bar-height);    padding: 0 .875rem;    border-bottom: 1px solid var(--color-line-hair);    background: linear-gradient(180deg, var(--color-surface-raised), var(--color-surface-raised-low)) var(--color-surface-raised-low);    box-shadow: inset 0 1px 0 var(--color-highlight);  }  /* Three marks, 11px each, 7px apart: discs of the line ink with a faint edge of their own. */  .window-controls {    --window-mark: var(--color-line-strong);    display: block;    width: 3.0625rem;    height: .6875rem;    background:      radial-gradient(circle at 5.5px 50%, var(--window-mark) 5px, transparent 5.5px),      radial-gradient(circle at 24.5px 50%, var(--window-mark) 5px, transparent 5.5px),      radial-gradient(circle at 43.5px 50%, var(--window-mark) 5px, transparent 5.5px);    @media (forced-colors: active) {      --window-mark: CanvasText;      forced-color-adjust: none;    }  }  .window-title {    grid-column: 2;    max-width: 100%;    margin: 0;    overflow: hidden;    color: var(--color-text-muted);    font: var(--font-weight-control) .8125rem/1.2 var(--font-family-sans);    font-feature-settings: inherit;    text-align: center;    text-overflow: ellipsis;    white-space: nowrap;  }  /* An address instead of a title: a small well in the middle of the bar, as a browser has. */  .window-address {    --icon-size: .75rem;    display: inline-flex;    grid-column: 2;    align-items: center;    justify-content: center;    gap: .375rem;    width: min(100%, 16rem);    min-width: 0;    height: 1.625rem;    padding: 0 .75rem;    border-radius: calc((var(--window-radius) - .25rem) * var(--corner-scale));    corner-shape: var(--corner-shape);    overflow: hidden;    background: var(--color-surface-inset);    color: var(--color-text-muted);    box-shadow: var(--shadow-pressed);    font: 400 .75rem/1 var(--font-family-sans);    font-feature-settings: inherit;    text-overflow: ellipsis;    white-space: nowrap;  }  /* What stands at the end of the bar. */  .window-end {    display: inline-flex;    grid-column: 3;    align-items: center;    justify-content: flex-end;    gap: .25rem;    min-width: 0;    color: var(--color-text-muted);  }  /* What the window shows. It has no padding: a picture or a video meets the frame. */  .window-body {    display: block;    flex: 1 1 auto;    min-width: 0;    min-height: 0;    margin: 0;  }}