css-device-frames
Version:
A collection of single-element, CSS-only application and device frames with support for multiple themes, customization via CSS custom properties, grid-based layouts, iframe elements, and scrolling content.
218 lines (214 loc) • 8.85 kB
CSS
.app-frame {
/* Defaults */
--background: #fff;
--bar-background: #f4f4f4 linear-gradient(to bottom, #fafafa, #f4f4f4);
--bar-height: 44px;
--border-color: #e3e3e3;
--border-radius: 8px;
--border-width: 1px;
--box-shadow: rgba(0, 0, 0, 0.08) 0px 10px 15px -3px, rgba(0, 0, 0, 0.03) 0px 4px 6px -2px;
--button-color: initial;
--color: initial;
--grid-columns: auto;
--grid-rows: auto;
--padding-h: 20px;
--padding-v: 20px;
--title: initial;
--title-color: #222;
--title-size: 0.875em;
--title-weight: 600;
--url: initial;
--url-background: #fff;
--url-border-radius: calc(var(--border-radius) * 0.6);
--url-border-width: 1px;
--url-color: #999;
}
.app-frame {
--bar-inset: 20px;
--button-inset: 20px;
--title-inset: 20px;
--url-inset: 10px;
display: block;
position: relative;
overflow: auto;
margin: 1em 0;
box-shadow: var(--box-shadow);
padding: var(--padding-v, 0) var(--padding-h, 0) ;
border: var(--border-width) solid var(--border-color);
border-radius: var(--border-radius);
background: var(--background);
color: var(--color);
flex-wrap: wrap;
grid-template-rows: var(--bar-height) var(--grid-rows);
grid-template-columns: var(--grid-columns);
}
.app-frame.dark {
--background: #262626;
--bar-background: #404040 linear-gradient(to bottom, #525252, #404040);
--border-color: #525252;
--color: #f5f5f5;
--title-color: #d4d4d4;
--url-background: #737373;
--url-border-width: 0;
--url-color: #d4d4d4;
}
.app-frame.wireframe {
--background: none;
--bar-background: none;
--border-width: 2px;
--url-border-width: 2px;
--url-background: none;
}
.app-frame.mac {
--button-gap: calc(var(--button-size) * 0.57);
--button-size: 12px;
--title-inset: calc((var(--button-inset) * 2) + (var(--button-size) * 3) + (var(--button-gap) * 2));
--url-inset: var(--title-inset);
}
.app-frame.win {
--button-gap: var(--button-inset);
--button-inset: 25px;
--button-size: 10px;
--button-stroke-width: 1px;
--title-inset: calc((var(--button-inset) * 2) + (var(--button-size) * 3) + (var(--button-gap) * 2));
--url-inset: var(--title-inset);
}
.app-frame.win {
--button-color-default: #ccc;
}
.app-frame.dark.win {
--button-color-default: #a3a3a3;
}
.app-frame.wireframe {
--button-color-default: #d4d4d4;
}
.app-frame.wireframe.dark {
--button-color-default: var(--border-color);
}
.app-frame, .app-frame::before, .app-frame::after {
box-sizing: border-box;
}
.app-frame::before {
content: "";
display: block;
height: var(--bar-height);
margin-top: calc(0px - var(--padding-v, 0px));
margin-left: calc(0px - var(--padding-h, 0px));
margin-right: calc(0px - var(--padding-h, 0px));
margin-bottom: var(--padding-v);
border-bottom-width: var(--border-width);
border-bottom-style: inherit;
border-bottom-color: var(--border-color);
border-top-left-radius: calc(var(--border-radius) - var(--border-width));
border-top-right-radius: calc(var(--border-radius) - var(--border-width));
background: var(--bar-background);
grid-column: 1/-1;
width: calc(100% + var(--padding-h, 0px) * 2);
}
.app-frame.mac::before {
background: radial-gradient(circle at calc(var(--button-inset) + var(--button-size) * 0.5) calc(var(--bar-height) / 2), var(--button-color, var(--button-color-default, #ff5f57)) calc(var(--button-size) / 2), transparent calc(var(--button-size) / 2)), radial-gradient(circle at calc(var(--button-inset) + var(--button-size) * 1.5 + var(--button-gap)) calc(var(--bar-height) / 2), var(--button-color, var(--button-color-default, #febc2e)) calc(var(--button-size) / 2), transparent calc(var(--button-size) / 2)), radial-gradient(circle at calc(var(--button-inset) + var(--button-size) * 2.5 + var(--button-gap) * 2) calc(var(--bar-height) / 2), var(--button-color, var(--button-color-default, #28c840)) calc(var(--button-size) / 2), transparent calc(var(--button-size) / 2)), var(--bar-background);
}
.app-frame.win::before {
background: no-repeat calc(100% - (var(--button-inset) + var(--button-size) * 2 + var(--button-gap) * 2))/var(--button-size) var(--button-size) linear-gradient(0deg, transparent calc(var(--button-size) / 2 - var(--button-stroke-width) / 2), var(--button-color, var(--button-color-default)) calc(var(--button-size) / 2 - var(--button-stroke-width) / 2) calc(var(--button-size) / 2 + var(--button-stroke-width) / 2), transparent calc(var(--button-size) / 2 + var(--button-stroke-width) / 2)), no-repeat calc(100% - (var(--button-inset) + var(--button-size) + var(--button-gap)))/var(--button-size) var(--button-size) linear-gradient(0deg, var(--button-color, var(--button-color-default)) var(--button-stroke-width), transparent var(--button-stroke-width) calc(var(--button-size) - var(--button-stroke-width)), var(--button-color, var(--button-color-default)) calc(var(--button-size) - var(--button-stroke-width))), no-repeat calc(100% - (var(--button-inset) + var(--button-size) + var(--button-gap)))/var(--button-size) var(--button-size) linear-gradient(90deg, var(--button-color, var(--button-color-default)) var(--button-stroke-width), transparent var(--button-stroke-width) calc(var(--button-size) - var(--button-stroke-width)), var(--button-color, var(--button-color-default)) calc(var(--button-size) - var(--button-stroke-width))), no-repeat calc(100% - var(--button-inset))/var(--button-size) var(--button-size) linear-gradient(45deg, transparent calc(var(--button-size) * 0.7225 - var(--button-stroke-width)), var(--button-color, var(--button-color-default)) calc(var(--button-size) * 0.7225 - var(--button-stroke-width)) calc(var(--button-size) * 0.7225 + var(--button-stroke-width) * 0.7225), transparent calc(var(--button-size) * 0.7225 + var(--button-stroke-width) * 0.7225)), no-repeat calc(100% - var(--button-inset))/var(--button-size) var(--button-size) linear-gradient(135deg, transparent calc(var(--button-size) * 0.7225 - var(--button-stroke-width)), var(--button-color, var(--button-color-default)) calc(var(--button-size) * 0.7225 - var(--button-stroke-width)) calc(var(--button-size) * 0.7225 + var(--button-stroke-width) * 0.7225), transparent calc(var(--button-size) * 0.7225 + var(--button-stroke-width) * 0.7225)), var(--bar-background);
}
.app-frame::after {
content: "";
position: absolute;
top: calc(var(--bar-height) / 2);
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif;
font-stretch: normal;
font-style: normal;
font-weight: normal;
line-height: 1;
letter-spacing: normal;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
transform: translate(0, -50%);
}
.app-frame.mac[data-title]::after, .app-frame.mac[data-url]::after {
right: var(--bar-inset);
}
.app-frame.win[data-title]::after, .app-frame.win[data-url]::after {
left: var(--bar-inset);
}
.app-frame.centered[data-title]::after, .app-frame.centered[data-url]::after {
left: 50%;
right: 0;
min-width: 40%;
max-width: 50%;
text-align: center;
transform: translate(-50%, -50%);
}
.app-frame[data-title]::after {
content: attr(data-title);
left: var(--title-inset);
right: var(--title-inset);
color: var(--title-color);
font-size: var(--title-size);
font-weight: var(--title-weight);
}
.app-frame[data-title=""]::after {
content: var(--title);
}
.app-frame[data-url]::after {
content: attr(data-url);
left: var(--url-inset);
right: var(--url-inset);
padding: 0 1.25em;
box-shadow: inset 0 0 0 var(--url-border-width) var(--border-color);
border-radius: var(--url-border-radius);
background: var(--url-background);
color: var(--url-color);
font-size: 0.8125em;
line-height: 2em;
line-height: clamp(1.8em, var(--bar-height) * 0.575, 2em);
}
.app-frame[data-url=""]::after {
content: var(--url);
}
.app-frame.borderless {
--padding-h: 0px;
--padding-v: 0px;
border: 0;
}
.app-frame.borderless::before {
margin: 0;
border: var(--border-width) solid var(--border-color);
border-top-left-radius: var(--border-radius);
border-top-right-radius: var(--border-radius);
}
.app-frame.borderless > *:only-child {
display: block;
max-width: 100%;
width: 100%;
margin: 0;
}
.app-frame > iframe:only-child {
display: block;
max-height: none;
max-width: none;
width: 100%;
border: 0;
margin: 0;
}
.app-frame.scrolling {
display: grid;
align-items: stretch;
padding: 0 ;
}
.app-frame.scrolling::before {
width: auto;
margin: 0;
}
.app-frame.scrolling > :only-child {
overflow: auto;
padding: var(--padding-v) var(--padding-h);
}
/*! CSS Device Frames v1.0.6
* https://github.com/jhildenbiddle/css-device-frames#readme
* (c) 2021-2024 John Hildenbiddle
* MIT license
*/
/*# sourceMappingURL=device-frames.css.map */