Modularize CSS; add reset, theme and fonts

Introduce reset.css and theme.css and refactor style.css
to import them via layers; add Unscii font files and preload links.
Add RSS XSL/CSS and a css-test page; remove legacy snes.min.css.
Tweak BaseLayout and contact layout (preloads, grid gaps). Rename index.astro to parallax.astro and
created new basic index page. Improve input styles and contact form placeholders
This commit is contained in:
badblocks 2026-01-30 09:33:21 -08:00
parent 7dd61775b3
commit 0350a4b8e3
No known key found for this signature in database
15 changed files with 1749 additions and 1458 deletions

137
public/reset.css Normal file
View file

@ -0,0 +1,137 @@
*,
*::after,
*::before {
font-feature-settings: "kern";
font-kerning: normal;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
box-sizing: border-box;
margin: 0;
padding: 0;
}
input:is([type="checkbox"], [type="radio"], [type="file"]),
select,
label,
button,
a {
cursor: pointer;
}
:where(html) {
color-scheme: light dark;
hanging-punctuation: first allow-end last;
interpolate-size: allow-keywords;
scroll-behavior: smooth;
scrollbar-gutter: stable;
text-size-adjust: none;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: transparent;
-webkit-font-smoothing: antialiased;
}
:where(html.translated-rtl) {
direction: rtl;
}
@media (prefers-reduced-motion: reduce) {
:where(html) {
scroll-behavior: auto;
}
}
:where(body) {
min-block-size: 100svb;
min-inline-size: 300px;
}
:where(canvas, img, picture, svg, video) {
block-size: auto;
border: none;
display: block;
max-inline-size: 100%;
}
:where(svg) {
fill: currentcolor;
}
:where(button, input, progress, select, textarea) {
appearance: none;
background: transparent;
border: none;
color: inherit;
font: inherit;
hanging-punctuation: none;
line-height: inherit;
text-align: start;
touch-action: manipulation;
}
:where(button) {
cursor: pointer;
user-select: none;
}
:where(textarea) {
resize: vertical;
}
:where(textarea:not([rows])) {
field-sizing: content;
}
:where(fieldset, iframe) {
border: none;
}
:where(p, li, h1, h2, h3, h4, h5, h6) {
overflow-wrap: break-word;
text-wrap: pretty;
}
:where(abbr[title]) {
border: none;
text-decoration: none;
}
:where(cite) {
font-style: inherit;
}
:where(small) {
font-size: inherit;
}
:where(li, ol, ul) {
list-style: none;
}
:where(dialog, [popover]) {
background: transparent;
border: none;
color: inherit;
margin: auto;
max-block-size: none;
max-inline-size: none;
position: fixed;
}
:where([popover]) {
inset: auto;
}
:where(dialog:not([open], [popover]), [popover]:not(:popover-open)) {
display: none;
}
:where([hidden]:not([hidden="until-found"])) {
display: none !important;
}
/* For Windows High Contrast Mode */
@media (forced-colors: active) {
button {
border: 1px solid;
}
}

74
public/rss.css Normal file
View file

@ -0,0 +1,74 @@
:root {
--db-light: 98.62% 0.014 84.58;
--db-dark: 40.05% 0.014 17.74;
--db-pink: 70.27% 0.192 13.7;
--db-blue: 62.78% 0.12 226;
}
* {
box-sizing: border-box;
font-family: sans-serif;
line-height: 1.4;
margin: 0;
padding: 0;
}
html {
background: oklch(var(--db-light));
color: oklch(var(--db-dark));
}
body {
padding: 1.5rem;
}
a {
color: oklch(var(--db-blue));
}
a:hover {
color: oklch(var(--db-pink));
text-decoration: none;
}
a:focus-visible {
color: oklch(var(--db-pink));
outline: 0.125rem solid oklch(var(--db-pink));
outline-offset: 0.125rem;
}
main,
header {
margin-block-end: 3rem;
margin-inline: auto;
max-inline-size: 80ch;
}
article {
margin-block-end: 3rem;
}
h1 {
font-size: 2.5rem;
line-height: 1.2;
margin-block: 1rem;
}
h2 {
font-size: 1.75rem;
margin-block: 2rem;
}
h3 {
font-size: 1.5rem;
margin-block: 1rem;
}
p {
font-size: 1.25rem;
margin-block-end: 1rem;
}
small {
font-size: 1rem;
}

49
public/rss.xsl Normal file
View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>RSS <xsl:value-of select="/rss/channel/title"/></title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="/rss.css"/>
</head>
<body>
<header>
<h1><xsl:value-of select="/rss/channel/title"/></h1>
<p><xsl:value-of select="/rss/channel/description"/></p>
<p>
<a>
<xsl:attribute name="href">
<xsl:value-of select="/rss/channel/link"/>
</xsl:attribute>
<xsl:value-of select="/rss/channel/link"/>
</a>
</p>
</header>
<main>
<h2>Recent Posts</h2>
<xsl:for-each select="/rss/channel/item">
<article>
<xsl:if test="title">
<h3>
<a rel="noopener noreferrer" target="_blank">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:value-of select="title"/>
</a>
</h3>
</xsl:if>
<p><xsl:value-of select="description"/></p>
<p>
<small>Published: <time><xsl:value-of select="pubDate"/></time></small>
</p>
</article>
</xsl:for-each>
</main>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

8
public/snes.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

401
public/theme.css Normal file
View file

@ -0,0 +1,401 @@
h1.giga {
font-size: var(--pt-double-canon);
}
h1.mega {
font-size: var(--pt-canon);
}
h1 {
font-size: var(--pt-double-great-primer);
}
h2 {
font-size: var(--pt-double-english);
}
h3 {
font-size: var(--pt-double-pica);
}
h4 {
font-size: var(--pt-paragon);
}
h5 {
font-size: var(--pt-great-primer);
}
h6 {
font-size: var(--pt-english);
}
small {
font-size: var(--pt-small-pica);
}
small.micro {
font-size: var(--pt-long-primer);
}
small.nano {
font-size: var(--pt-bourgeois);
}
small.pico {
font-size: var(--pt-minion);
}
body {
background-color: var(--color-bg);
background-image: radial-gradient(
var(--color-accent-transparent),
black 120%
);
color: var(--color-fg);
column-gap: var(--gutter-large);
display: grid;
font-size: var(--pt-pica);
grid-template-rows: auto 1fr auto;
height: 100dvb;
left: 0;
overflow-x: hidden;
padding-inline: var(--page-padding-inline);
place-items: center;
position: absolute;
row-gap: var(--stack-large);
text-shadow: 0 0 5px var(--color-glow);
top: 0;
width: 100dvi;
}
body::after {
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.25),
rgba(0, 0, 0, 0.25) 1px,
transparent 1px,
transparent 2px
);
content: "";
height: 100dvb;
left: 0;
pointer-events: none;
position: absolute;
top: 0;
width: 100dvi;
}
::selection {
background: var(--color-accent);
text-shadow: none;
}
header,
main,
footer {
width: 100%;
}
header,
footer {
padding-block: var(--stack-large);
text-align: center;
a {
text-decoration: none;
}
}
nav {
padding-block: var(--stack-small);
padding-inline: var(--gutter-small);
width: 100%;
}
nav ul {
column-gap: var(--gutter-large);
display: flex;
flex-wrap: wrap;
justify-content: center;
list-style: none;
margin-block-start: 0;
row-gap: var(--stack-large);
}
nav li {
align-content: center;
white-space: nowrap;
}
.iconBox {
display: inline-block;
height: 19px;
width: 19px;
}
p,
ul {
margin-block-end: var(--stack-large);
max-inline-size: var(--line-length);
}
form p {
margin-block-end: none;
}
a {
color: var(--color-fg);
margin: 0 -1ch;
padding: 0 1ch;
text-decoration: underline;
text-decoration-color: var(--color-glow);
&:hover::before {
color: var(--color-glow);
content: "[";
}
&:hover::after {
color: var(--color-glow);
content: "]";
}
&:hover {
color: var(--color-fg);
padding: 0;
text-decoration: none;
}
}
ul {
list-style-type: square;
}
fieldset {
border: 2px solid var(--color-fg);
padding-block: var(--stack-small);
padding-inline: var(--gutter-small);
}
label {
display: block;
}
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]) {
align-items: center;
column-gap: var(--gutter-large);
display: flex;
margin-block: var(--stack-large);
}
/* TODO: use textarea-wrapper strategy to implement invisible inputs idea,
but have the text-glow effect done on the ::after pseudo-element and hide
the input when it isnt focused, and swap when focused */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="search"],
input[type="url"],
input[type="tel"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="datetime-local"],
textarea,
.textarea-wrapper::after,
select {
background-color: var(--color-bg);
border: 2px solid var(--color-accent);
padding-block: var(--stack-small);
padding-inline: var(--gutter-small);
transition:
border-color 0.5s,
box-shadow 0.5s;
width: 100%;
}
textarea,
.textarea-wrapper::after {
grid-area: 1 / 1 / 2 / 2; /* Place on top of each other */
min-height: calc(2rlh + (var(--stack-small) * 2) - 2px);
}
.textarea-wrapper {
display: grid;
}
.textarea-wrapper::after {
content: attr(data-replicated-value) " "; /* Needed to preventy jumpy behavior */
visibility: hidden;
white-space: pre-wrap;
}
.textarea-wrapper > textarea {
overflow: hidden;
resize: none;
}
input:focus,
textarea:focus,
select:focus {
box-shadow: 0 0 5px var(--color-glow);
outline: none;
}
input:disabled,
textarea:disabled,
select:disabled,
button:disabled,
fieldset:disabled {
cursor: not-allowed;
opacity: 0.5;
}
button,
input[type="submit"],
input[type="reset"] {
background-color: var(--color-accent);
box-shadow: 0 0 2px var(--color-glow);
color: var(--color-bg);
margin-block: var(--stack-small);
padding-block: var(--stack-small);
padding-inline: var(--gutter-small);
transition: background-color 0.5s;
text-align: center;
}
button:hover:enabled,
input[type="submit"]:hover:enabled,
input[type="reset"]:hover:enabled {
background-color: var(--color-accent-bright);
}
button:active:enabled,
input[type="submit"]:active:enabled,
input[type="reset"]:active:enabled {
background-color: var(--color-accent-bright);
}
/*input[type="checkbox"],
input[type="radio"] {
appearance: none;
background-color: var(--color-bg);
border: 2px solid var(--color-fg);
cursor: pointer;
height: var(--pt-english);
position: relative;
vertical-align: middle;
width: var(--pt-english);
}
input[type="checkbox"] {
border-radius: 3px;
}
input[type="radio"] {
border-radius: 50%;
}
input[type="checkbox"]:checked,
input[type="radio"]:checked {
background-color: var(--color-accent);
}
input[type="checkbox"]:checked::after {
color: var(--color-accent);
content: "✓";
font-size: var(--pt-long-primer);
left: 2px;
position: absolute;
top: -1px;
}
input[type="radio"]:checked::after {
background-color: var(--color-accent);
border-radius: 50%;
content: "";
height: var(--pt-minion);
left: 3px;
position: absolute;
top: 3px;
width: var(--pt-minion);
}
select {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23333' viewBox='0 0 16 16'%3E%3Cpath d='M7.247 11.14L2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/%3E%3C/svg%3E");
background-position: calc(100% - 8px) center;
background-repeat: no-repeat;
padding-block-end: var(--stack-small);
}
input[type="file"] {
background-color: var(--color-bg);
border: 2px dashed var(--color-fg);
cursor: pointer;
padding: 20px;
text-align: center;
}
input[type="file"]::file-selector-button {
background-color: var(--color-accent);
border: none;
border-radius: 4px;
color: var(--bg-color);
cursor: pointer;
font-family: inherit;
margin-right: 10px;
padding: 8px 16px;
}
input[type="range"] {
appearance: none;
background-color: var(--color-fg);
border-radius: 3px;
height: 6px;
margin: 10px 0;
width: 100%;
}
input[type="range"]::-webkit-slider-thumb {
appearance: none;
background-color: var(--color-accent);
border: 2px solid var(--bg-color);
border-radius: 50%;
cursor: pointer;
height: 18px;
width: 18px;
}
input[type="color"] {
border: 2px solid var(--color-fg);
border-radius: 4px;
cursor: pointer;
height: 40px;
padding: 2px;
width: 60px;
}
input:invalid,
textarea:invalid,
select:invalid {
border-color: var(--color-accent);
}
label.required::after {
color: var(--color-accent);
content: "*";
margin-left: 4px;
}
button,
input[type="submit"],
input[type="reset"] {
background-color: var(--color-accent);
border: 2px solid var(--color-accent);
border-radius: 4px;
color: var(--bg-color);
cursor: pointer;
font-family: inherit;
font-size: 1rem;
padding: 10px 20px;
transition: all 0.2s;
}
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover {
background-color: var(--color-fg);
border-color: var(--color-fg);
transform: translateY(-1px);
}
button:active,
input[type="submit"]:active,
input[type="reset"]:active {
transform: translateY(1px);
}
progress {
background-color: var(--color-bg);
border: 2px solid var(--color-fg);
border-radius: 4px;
height: 20px;
width: 100%;
}
progress::-webkit-progress-bar {
background-color: var(--color-bg);
border-radius: 2px;
}
progress::-webkit-progress-value {
background-color: var(--color-accent);
border-radius: 2px;
}
*/

BIN
public/unscii-16.ttf Normal file

Binary file not shown.

BIN
public/unscii-16.woff Normal file

Binary file not shown.

BIN
public/unscii-8.ttf Normal file

Binary file not shown.

BIN
public/unscii-8.woff Normal file

Binary file not shown.

View file

@ -3,9 +3,14 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preload" as="font" type="font/woff" href="unscii-16.woff" />
<link rel="preload" as="font" type="font/woff" href="unscii-8.woff" />
<link rel="preload" href="reset.css" as="style" />
<link rel="preload" href="theme.css" as="style" />
<link rel="stylesheet" type="text/css" href="/style.css" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<!--<link rel="stylesheet" type="text/css" href="/style.css" />--> <meta name="darkreader-lock" />
<link rel="sitemap" href="/sitemap-index.xml" /> <link rel="sitemap" href="/sitemap-index.xml" />
<script> <script>
const yearSpan = document.querySelector("#copyright-year"); const yearSpan = document.querySelector("#copyright-year");
@ -13,131 +18,21 @@
yearSpan.innerHTML = new Date().getFullYear().toString(); yearSpan.innerHTML = new Date().getFullYear().toString();
} }
</script> </script>
<style is:inline>
@font-face {
font-family: "unscii16";
src:
url("unscii-16.woff") format("woff"),
url("unscii-16.ttf") format("ttf");
}
@font-face {
font-family: "unscii8";
src:
url("unscii-8.woff") format("woff"),
url("unscii-8.ttf") format("ttf");
}
a {
color: #333;
text-decoration: none;
&:visited {
color: #555;
}
&:hover {
color: #555;
text-decoration: underline;
text-decoration-style: dashed;
}
}
p a {
margin: 0 -0.5rem;
padding: 0 0.5rem;
&:hover::before {
content: "[";
}
&:hover::after {
content: "]";
}
&:hover {
text-decoration: none;
padding: 0;
}
}
ul {
list-style-type: square;
}
</style>
<style>
h1 {
font-family: "unscii16", monospace;
font-size: 32px;
text-align: center;
}
:root {
--min-body-width: 30ch;
--max-body-width: 120ch;
font-size: 16px;
font-family: "unscii16", monospace;
font-weight: 400;
font-style: normal;
}
body {
display: grid;
grid-template-columns:
minmax(0.8rem, 1fr)
minmax(var(--min-body-width), var(--max-body-width))
minmax(0.8rem, 1fr);
grid-template-rows: auto 1fr auto;
grid-template-areas:
". header ."
". content ."
". footer .";
min-height: 100vh;
place-items: center;
width: 100%;
min-width: var(--min-body-width);
position: absolute;
top: 0;
left: 0;
background-color: #ccc;
color: #000;
}
header {
grid-area: header;
}
header h1 {
text-transform: none;
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
nav li {
align-content: center;
}
nav li select {
margin: 0;
}
main {
grid-area: content;
}
footer {
grid-area: footer;
display: grid;
place-items: center;
}
</style>
<slot name="head" /> <slot name="head" />
</head> </head>
<body x-data="{ theme: 'winternight'}"> <body x-data="{ theme: 'winternight'}">
<header> <header>
<h1><a href="/">badblocks.dev</a></h1> <h1>badblocks.dev</h1>
<nav> <nav>
<ul> <ul>
<li> <!-- <li>
<select id="theme" x-model="theme"> <select id="theme" x-model="theme">
<option value="winternight">Winternight</option> <option value="winternight">Winternight</option>
<option value="sunnyvale-forest">SunnyVale</option> <option value="sunnyvale-forest">SunnyVale</option>
<option value="city-destroyed">Apocalypse</option> <option value="city-destroyed">Apocalypse</option>
</select> </select>
</li> </li> -->
<li><a href="/">Home</a></li>
<li><a href="/contact">Contact</a></li> <li><a href="/contact">Contact</a></li>
<li><a href="https://git.badblocks.dev" target="_blank">Git</a></li> <li><a href="https://git.badblocks.dev" target="_blank">Git</a></li>
</ul> </ul>

View file

@ -80,9 +80,10 @@ const msgValue = pickValue("msg");
<style> <style>
form { form {
display: grid; display: grid;
gap: 1rem; row-gap: var(--stack-large);
column-gap: var(--gutter-large);
width: 100%; width: 100%;
margin: 0 auto; margin-inline: auto;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
grid-template-areas: grid-template-areas:
"header header" "header header"
@ -91,16 +92,9 @@ const msgValue = pickValue("msg");
"captcha otp" "captcha otp"
"lbtn rbtn"; "lbtn rbtn";
} }
.hidden {
display: none;
visibility: hidden;
}
#header { #header {
grid-area: header; grid-area: header;
} }
label {
text-align: left;
}
label[for="name"] { label[for="name"] {
grid-area: name; grid-area: name;
} }
@ -115,16 +109,13 @@ const msgValue = pickValue("msg");
} }
label[for="captcha"] { label[for="captcha"] {
grid-area: captcha; grid-area: captcha;
a {
color: #000;
}
} }
#captchaStatus { #captchaStatus {
padding: 0.8rem 0; padding-block: calc(2px + (var(--stack-small) * 1));
cursor: text;
} }
button { #statusText {
height: 39px; margin-inline-start: 0.5rem;
padding: 8px 12px;
} }
button#reset { button#reset {
grid-area: lbtn; grid-area: lbtn;
@ -155,9 +146,6 @@ const msgValue = pickValue("msg");
<title slot="head">Contact</title> <title slot="head">Contact</title>
<Fragment slot="content"> <Fragment slot="content">
<h2>Contact</h2> <h2>Contact</h2>
<p><a href="https://kagi.com">Link Style 1</a></p><a href="https://kagi.com"
>Link Style 2</a
>
{ {
(nextAction != "complete" && ( (nextAction != "complete" && (
<form method="post" x-data="{}" action={actions.contact.submitForm}> <form method="post" x-data="{}" action={actions.contact.submitForm}>
@ -167,7 +155,7 @@ const msgValue = pickValue("msg");
{result?.error.message} {result?.error.message}
Please correct any errors and try again. Please correct any errors and try again.
</p> </p>
)) || <p>Use the below form to shoot me a quick text!</p>} )) || <p>Use this form to shoot me a quick text!</p>}
</div> </div>
<fieldset id="send_otp_fields" disabled={nextAction != "send_otp"}> <fieldset id="send_otp_fields" disabled={nextAction != "send_otp"}>
<label for="name"> <label for="name">
@ -177,7 +165,7 @@ const msgValue = pickValue("msg");
id="name" id="name"
name="name" name="name"
aria-describedby="name" aria-describedby="name"
value="Bad Blocks" placeholder="Alice Bob"
/> />
{error.name && <p id="error_name">{error.name.join(",")}</p>} {error.name && <p id="error_name">{error.name.join(",")}</p>}
</label> </label>
@ -188,14 +176,21 @@ const msgValue = pickValue("msg");
id="phone" id="phone"
name="phone" name="phone"
aria-describedby="error_phone" aria-describedby="error_phone"
value="2067452154" placeholder="555-555-5555"
/> />
{error.phone && <p id="error_phone">{error.phone.join(",")}</p>} {error.phone && <p id="error_phone">{error.phone.join(",")}</p>}
</label> </label>
<label for="msg"> <label for="msg">
Msg Msg
{/* prettier-ignore */} <div class="textarea-wrapper">
<textarea id="msg" name="msg" aria-describedby="error_msg">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean tortor neque, ullamcorper molestie fermentum quis, vulputate et lacus.</textarea> <textarea
id="msg"
name="msg"
oninput="this.parentNode.dataset.replicatedValue = this.value"
aria-describedby="error_msg"
placeholder="I think badblocks rocks! Lorem ipsum dolor sit amet, consectetur adipiscing elit."
/>
</div>
{error.msg && <p id="error_msg">{error.msg.join(",")}</p>} {error.msg && <p id="error_msg">{error.msg.join(",")}</p>}
</label> </label>
<button <button
@ -206,18 +201,17 @@ const msgValue = pickValue("msg");
disabled={nextAction != "send_otp"} disabled={nextAction != "send_otp"}
class={nextAction != "send_otp" ? "hidden" : ""} class={nextAction != "send_otp" ? "hidden" : ""}
> >
Send Verification Code! Verify Me!
</button> </button>
</fieldset> </fieldset>
<fieldset id="send_msg_fields" disabled={nextAction != "send_msg"}> <fieldset id="send_msg_fields" disabled={nextAction != "send_msg"}>
<label for="otp" class={nextAction != "send_msg" ? "hidden" : ""}> <label for="otp">
Verification Code Verification Code
<input <input
type="text" type="text"
id="otp" id="otp"
name="otp" name="otp"
aria-describedby="error_otp" aria-describedby="error_otp"
placeholder="123456"
/> />
{error.otp && <p id="error_otp">{error.otp.join(",")}</p>} {error.otp && <p id="error_otp">{error.otp.join(",")}</p>}
</label> </label>
@ -231,7 +225,7 @@ const msgValue = pickValue("msg");
Go Back! Go Back!
</button> </button>
<button id="send_msg" name="action" value="send_msg" type="submit"> <button id="send_msg" name="action" value="send_msg" type="submit">
Text Me! Send ittt!
</button> </button>
</fieldset> </fieldset>
<label for="captcha"> <label for="captcha">
@ -239,23 +233,25 @@ const msgValue = pickValue("msg");
<a href="https://capjs.js.org/" tabindex="-1">Captcha</a> <a href="https://capjs.js.org/" tabindex="-1">Captcha</a>
<input type="hidden" id="captcha" name="captcha" /> <input type="hidden" id="captcha" name="captcha" />
<div id="captchaStatus"> <div id="captchaStatus">
<iconify-icon id="initIcon" icon="line-md:loading-loop" /> <div class="iconBox">
<iconify-icon <iconify-icon id="initIcon" icon="line-md:loading-loop" />
id="completeIcon" <iconify-icon
icon="line-md:circle-to-confirm-circle-transition" id="completeIcon"
class="hidden" icon="line-md:circle-to-confirm-circle-transition"
/> class="hidden"
<iconify-icon />
id="errorIcon" <iconify-icon
icon="line-md:alert-circle-loop" id="errorIcon"
class="hidden" icon="line-md:alert-circle-loop"
/> class="hidden"
<iconify-icon />
id="progressIcon" <iconify-icon
icon="line-md:speedometer-loop" id="progressIcon"
class="hidden" icon="line-md:speedometer-loop"
/> class="hidden"
&nbsp;<span id="statusText">Loading...</span> />
</div>
<span id="statusText">Loading...</span>
</div> </div>
{error.captcha && <p id="error_name">{error.captcha.join(",")}</p>} {error.captcha && <p id="error_name">{error.captcha.join(",")}</p>}
</label> </label>

757
src/pages/css-test.astro Normal file
View file

@ -0,0 +1,757 @@
---
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preload" as="font" type="font/woff" href="unscii-16.woff" />
<link rel="preload" as="font" type="font/woff" href="unscii-8.woff" />
<link rel="preload" href="reset.css" as="style" />
<link rel="preload" href="theme.css" as="style" />
<link rel="stylesheet" type="text/css" href="/style.css" />
<title>HTML5 Test Page</title>
</head>
<body>
<div id="top" role="document">
<header>
<h1>HTML5 Test Page</h1>
<p>
This is a test page filled with common HTML elements to be used to
provide visual feedback whilst building CSS systems and frameworks.
</p>
</header>
<nav>
<ul>
<li>
<a href="#text">Text</a>
<ul>
<li><a href="#text__headings">Headings</a></li>
<li><a href="#text__paragraphs">Paragraphs</a></li>
<li><a href="#text__lists">Lists</a></li>
<li><a href="#text__blockquotes">Blockquotes</a></li>
<li><a href="#text__details">Details / Summary</a></li>
<li><a href="#text__address">Address</a></li>
<li><a href="#text__hr">Horizontal rules</a></li>
<li><a href="#text__tables">Tabular data</a></li>
<li><a href="#text__code">Code</a></li>
<li><a href="#text__inline">Inline elements</a></li>
<li><a href="#text__comments">HTML Comments</a></li>
</ul>
</li>
<li>
<a href="#embedded">Embedded content</a>
<ul>
<li><a href="#embedded__images">Images</a></li>
<li><a href="#embedded__bgimages">Background images</a></li>
<li><a href="#embedded__audio">Audio</a></li>
<li><a href="#embedded__video">Video</a></li>
<li><a href="#embedded__canvas">Canvas</a></li>
<li><a href="#embedded__meter">Meter</a></li>
<li><a href="#embedded__progress">Progress</a></li>
<li><a href="#embedded__svg">Inline SVG</a></li>
<li><a href="#embedded__iframe">IFrames</a></li>
<li><a href="#embedded__embed">Embed</a></li>
<li><a href="#embedded__object">Object</a></li>
</ul>
</li>
<li>
<a href="#forms">Form elements</a>
<ul>
<li><a href="#forms__input">Input fields</a></li>
<li><a href="#forms__select">Select menus</a></li>
<li><a href="#forms__checkbox">Checkboxes</a></li>
<li><a href="#forms__radio">Radio buttons</a></li>
<li><a href="#forms__textareas">Textareas</a></li>
<li><a href="#forms__html5">HTML5 inputs</a></li>
<li><a href="#forms__action">Action buttons</a></li>
</ul>
</li>
</ul>
</nav>
<main>
<section id="text">
<header><h1>Text</h1></header>
<article id="text__headings">
<header>
<h2>Headings</h2>
</header>
<div>
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__paragraphs">
<header><h2>Paragraphs</h2></header>
<div>
<p>
A paragraph (from the Greek paragraphos, “to write beside” or
“written beside”) is a self-contained unit of a discourse in
writing dealing with a particular point or idea. A paragraph
consists of one or more sentences. Though not required by the
syntax of any language, paragraphs are usually an expected part
of formal writing, used to organize longer prose.
</p>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__blockquotes">
<header><h2>Blockquotes</h2></header>
<div>
<blockquote>
<p>
A block quotation (also known as a long quotation or extract)
is a quotation in a written document, that is set off from the
main text as a paragraph, or block of text.
</p>
<p>
It is typically distinguished visually using indentation and a
different typeface or smaller size quotation. It may or may
not include a citation, usually placed at the bottom.
</p>
<cite><a href="#!">Said no one, ever.</a></cite>
</blockquote>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__lists">
<header><h2>Lists</h2></header>
<div>
<h3>Definition list</h3>
<dl>
<dt>Definition List Title</dt>
<dd>This is a definition list division.</dd>
</dl>
<h3>Ordered List</h3>
<ol type="1">
<li>List Item 1</li>
<li>
List Item 2
<ol type="A">
<li>List Item 1</li>
<li>
List Item 2
<ol type="a">
<li>List Item 1</li>
<li>
List Item 2
<ol type="I">
<li>List Item 1</li>
<li>
List Item 2
<ol type="i">
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ol>
</li>
<li>List Item 3</li>
</ol>
</li>
<li>List Item 3</li>
</ol>
</li>
<li>List Item 3</li>
</ol>
</li>
<li>List Item 3</li>
</ol>
<h3>Unordered List</h3>
<ul>
<li>List Item 1</li>
<li>
List Item 2
<ul>
<li>List Item 1</li>
<li>
List Item 2
<ul>
<li>List Item 1</li>
<li>
List Item 2
<ul>
<li>List Item 1</li>
<li>
List Item 2
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</li>
<li>List Item 3</li>
</ul>
</li>
<li>List Item 3</li>
</ul>
</li>
<li>List Item 3</li>
</ul>
</li>
<li>List Item 3</li>
</ul>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__blockquotes">
<header><h1>Blockquotes</h1></header>
<div>
<blockquote>
<p>
A block quotation (also known as a long quotation or extract)
is a quotation in a written document, that is set off from the
main text as a paragraph, or block of text.
</p>
<p>
It is typically distinguished visually using indentation and a
different typeface or smaller size quotation. It may or may
not include a citation, usually placed at the bottom.
</p>
<cite><a href="#!">Said no one, ever.</a></cite>
</blockquote>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__details">
<header><h1>Details / Summary</h1></header>
<details>
<summary>Expand for details</summary>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum,
odio! Odio natus ullam ad quaerat, eaque necessitatibus, aliquid
distinctio similique voluptatibus dicta consequuntur animi.
Quaerat facilis quidem unde eos! Ipsa.
</p>
</details>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__address">
<header><h1>Address</h1></header>
<address>
Written by <a href="mailto:webmaster@example.com">Jon Doe</a>.<br
/>
Visit us at:<br />
Example.com<br />
Box 564, Disneyland<br />
USA
</address>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__hr">
<header><h2>Horizontal rules</h2></header>
<div>
<hr />
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__tables">
<header><h2>Tabular data</h2></header>
<table>
<caption>Table Caption</caption>
<thead>
<tr>
<th>Table Heading 1</th>
<th>Table Heading 2</th>
<th>Table Heading 3</th>
<th>Table Heading 4</th>
<th>Table Heading 5</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Table Footer 1</th>
<th>Table Footer 2</th>
<th>Table Footer 3</th>
<th>Table Footer 4</th>
<th>Table Footer 5</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>Table Cell 1</td>
<td>Table Cell 2</td>
<td>Table Cell 3</td>
<td>Table Cell 4</td>
<td>Table Cell 5</td>
</tr>
<tr>
<td>Table Cell 1</td>
<td>Table Cell 2</td>
<td>Table Cell 3</td>
<td>Table Cell 4</td>
<td>Table Cell 5</td>
</tr>
<tr>
<td>Table Cell 1</td>
<td>Table Cell 2</td>
<td>Table Cell 3</td>
<td>Table Cell 4</td>
<td>Table Cell 5</td>
</tr>
<tr>
<td>Table Cell 1</td>
<td>Table Cell 2</td>
<td>Table Cell 3</td>
<td>Table Cell 4</td>
<td>Table Cell 5</td>
</tr>
</tbody>
</table>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__code">
<header><h2>Code</h2></header>
<div>
<p><strong>Keyboard input:</strong> <kbd>Cmd</kbd></p>
<p>
<strong>Inline code:</strong>
<code>&lt;div&gt;code&lt;/div&gt;</code>
</p>
<p>
<strong>Sample output:</strong>
<samp>This is sample output from a computer program.</samp>
</p>
<h2>Pre-formatted text</h2>
<pre>
P R E F O R M A T T E D T E X T
! " # $ % &amp; ' ( ) * + , - . /
0 1 2 3 4 5 6 7 8 9 : ; &lt; = &gt; ?
@ A B C D E F G H I J K L M N O
P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o
p q r s t u v w x y z {"{ | }"} ~ </pre>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__inline">
<header><h2>Inline elements</h2></header>
<div>
<p><a href="#!">This is a text link</a>.</p>
<p>
<strong>Strong is used to indicate strong importance.</strong>
</p>
<p><em>This text has added emphasis.</em></p>
<p>
The <b>b element</b> is stylistically different text from normal text,
without any special importance.
</p>
<p>
The <i>i element</i> is text that is offset from the normal text.
</p>
<p>
The <u>u element</u> is text with an unarticulated, though explicitly
rendered, non-textual annotation.
</p>
<p>
<del>This text is deleted</del> and <ins
>This text is inserted</ins
>.
</p>
<p><s>This text has a strikethrough</s>.</p>
<p>Superscript<sup>®</sup>.</p>
<p>Subscript for things like H<sub>2</sub>O.</p>
<p>
<small>This small text is small for fine print, etc.</small>
</p>
<p>
Abbreviation: <abbr title="HyperText Markup Language">HTML</abbr
>
</p>
<p>
<q
cite="https://developer.mozilla.org/en-US/docs/HTML/Element/q"
>This text is a short inline quotation.</q
>
</p>
<p><cite>This is a citation.</cite></p>
<p>The <dfn>dfn element</dfn> indicates a definition.</p>
<p>The <mark>mark element</mark> indicates a highlight.</p>
<p>
The <var>variable element</var>, such as <var>x</var> = <var
>y</var
>.
</p>
<p>
The time element: <time datetime="2013-04-06T12:32+00:00"
>2 weeks ago</time
>
</p>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="text__comments">
<header><h2>HTML Comments</h2></header>
<div>
<p>
There is comment here: <!--This comment should not be displayed-->
</p>
<p>
There is a comment spanning multiple tags and lines below here.
</p>
<!--<p><a href="#!">This is a text link. But it should not be displayed in a comment</a>.</p>
              <p><strong>Strong is used to indicate strong importance. But, it should not be displayed in a comment</strong></p>
              <p><em>This text has added emphasis. But, it should not be displayed in a comment</em></p>-->
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
</section>
<section id="embedded">
<header><h2>Embedded content</h2></header>
<article id="embedded__images">
<header><h2>Images</h2></header>
<div>
<h3>Plain <code>&lt;img&gt;</code> element</h3>
<p>
<img
src="https://placekitten.com/480/480"
alt="Photo of a kitten"
/>
</p>
<h3>
<code>&lt;figure&gt;</code> element with <code>&lt;img&gt;</code
> element
</h3>
<figure>
<img
src="https://placekitten.com/420/420"
alt="Photo of a kitten"
/>
</figure>
<h3>
<code>&lt;figure&gt;</code> element with <code>&lt;img&gt;</code
> and <code>&lt;figcaption&gt;</code> elements
</h3>
<figure>
<img
src="https://placekitten.com/420/420"
alt="Photo of a kitten"
/>
<figcaption>Here is a caption for this image.</figcaption>
</figure>
<h3>
<code>&lt;figure&gt;</code> element with a <code
>&lt;picture&gt;</code
> element
</h3>
<figure>
<picture>
<source
srcset="https://placekitten.com/800/800"
media="(min-width: 800px)"
/>
<img
src="https://placekitten.com/420/420"
alt="Photo of a kitten"
/>
</picture>
</figure>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__bgimages">
<header><h2>Background images</h2></header>
<div
style="background-image:url('https://placekitten.com/300/300'); width:300px; height: 300px;"
>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__audio">
<header><h2>Audio</h2></header>
<div>
<audio controls=""
><source
src="https://dl.espressif.com/dl/audio/ff-16b-2c-44100hz.aac"
/>audio</audio>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__video">
<header><h2>Video</h2></header>
<div>
<video controls=""
><source
src="https://upload.wikimedia.org/wikipedia/commons/f/f3/Big_Buck_Bunny_first_23_seconds_1080p.ogv"
/>video</video
>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__canvas">
<header><h2>Canvas</h2></header>
<div><canvas>canvas</canvas></div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__meter">
<header><h2>Meter</h2></header>
<div><meter value="2" min="0" max="10">2 out of 10</meter></div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__progress">
<header><h2>Progress</h2></header>
<div><progress>progress</progress></div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__svg">
<header><h2>Inline SVG</h2></header>
<div>
<svg width="100px" height="100px"
><circle cx="100" cy="100" r="100" fill="#1fa3ec"></circle></svg
>
</div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__iframe">
<header><h2>IFrame</h2></header>
<div><iframe src="index.html" height="300"></iframe></div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__embed">
<header><h2>Embed</h2></header>
<div><embed src="index.html" height="300" /></div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
<article id="embedded__object">
<header><h2>Object</h2></header>
<div><object data="index.html" height="300"></object></div>
<footer><p><a href="#top">Top</a></p></footer>
</article>
</section>
<section id="forms">
<header><h2>Form elements</h2></header>
<form>
<fieldset id="forms__input">
<legend>Input fields</legend>
<p>
<label for="input__text">Text Input</label>
<input id="input__text" type="text" placeholder="Text Input" />
</p>
<p>
<label for="input__password">Password</label>
<input
id="input__password"
type="password"
placeholder="Type your Password"
/>
</p>
<p>
<label for="input__webaddress">Web Address</label>
<input
id="input__webaddress"
type="url"
placeholder="https://yoursite.com"
/>
</p>
<p>
<label for="input__emailaddress">Email Address</label>
<input
id="input__emailaddress"
type="email"
placeholder="name@email.com"
/>
</p>
<p>
<label for="input__phone">Phone Number</label>
<input
id="input__phone"
type="tel"
placeholder="(999) 999-9999"
/>
</p>
<p>
<label for="input__search">Search</label>
<input
id="input__search"
type="search"
placeholder="Enter Search Term"
/>
</p>
<p>
<label for="input__text2">Number Input</label>
<input
id="input__text2"
type="number"
placeholder="Enter a Number"
/>
</p>
<p>
<label for="input__file">File Input</label>
<input id="input__file" type="file" />
</p>
</fieldset>
<p><a href="#top">Top</a></p>
<fieldset id="forms__select">
<legend>Select menus</legend>
<p>
<label for="select">Select</label>
<select id="select">
<optgroup label="Option Group">
<option>Option One</option>
<option>Option Two</option>
<option>Option Three</option>
</optgroup>
</select>
</p>
<p>
<label for="select_multiple">Select (multiple)</label>
<select id="select_multiple" multiple="multiple">
<optgroup label="Option Group">
<option>Option One</option>
<option>Option Two</option>
<option>Option Three</option>
</optgroup>
</select>
</p>
</fieldset>
<p><a href="#top">Top</a></p>
<fieldset id="forms__checkbox">
<legend>Checkboxes</legend>
<ul>
<li>
<label for="checkbox1"
><input
id="checkbox1"
name="checkbox"
type="checkbox"
checked="checked"
/> Choice A</label
>
</li>
<li>
<label for="checkbox2"
><input id="checkbox2" name="checkbox" type="checkbox" /> Choice
B</label
>
</li>
<li>
<label for="checkbox3"
><input id="checkbox3" name="checkbox" type="checkbox" /> Choice
C</label
>
</li>
</ul>
</fieldset>
<p><a href="#top">Top</a></p>
<fieldset id="forms__radio">
<legend>Radio buttons</legend>
<ul>
<li>
<label for="radio1"
><input
id="radio1"
name="radio"
type="radio"
checked="checked"
/> Option 1</label
>
</li>
<li>
<label for="radio2"
><input id="radio2" name="radio" type="radio" /> Option 2</label
>
</li>
<li>
<label for="radio3"
><input id="radio3" name="radio" type="radio" /> Option 3</label
>
</li>
</ul>
</fieldset>
<p><a href="#top">Top</a></p>
<fieldset id="forms__textareas">
<legend>Textareas</legend>
<p>
<label for="textarea">Textarea</label>
<textarea
id="textarea"
rows="8"
cols="48"
placeholder="Enter your message here"></textarea>
</p>
</fieldset>
<p><a href="#top">Top</a></p>
<fieldset id="forms__html5">
<legend>HTML5 inputs</legend>
<p>
<label for="ic">Color input</label>
<input type="color" id="ic" value="#000000" />
</p>
<p>
<label for="in">Number input</label>
<input type="number" id="in" min="0" max="10" value="5" />
</p>
<p>
<label for="ir">Range input</label>
<input type="range" id="ir" value="10" />
</p>
<p>
<label for="idd">Date input</label>
<input type="date" id="idd" value="1970-01-01" />
</p>
<p>
<label for="idm">Month input</label>
<input type="month" id="idm" value="1970-01" />
</p>
<p>
<label for="idw">Week input</label>
<input type="week" id="idw" value="1970-W01" />
</p>
<p>
<label for="idt">Datetime input</label>
<input type="datetime" id="idt" value="1970-01-01T00:00:00Z" />
</p>
<p>
<label for="idtl">Datetime-local input</label>
<input
type="datetime-local"
id="idtl"
value="1970-01-01T00:00"
/>
</p>
<p>
<label for="idl">Datalist</label>
<input type="text" id="idl" list="example-list" />
<datalist id="example-list">
<option value="Example #1"></option>
<option value="Example #2"></option>
<option value="Example #3"></option>
</datalist>
</p>
</fieldset>
<p><a href="#top">Top</a></p>
<fieldset id="forms__action">
<legend>Action buttons</legend>
<p>
<input type="submit" value="<input type=submit>" />
<input type="button" value="<input type=button>" />
<input type="reset" value="<input type=reset>" />
<input type="submit" value="<input disabled>" disabled />
</p>
<p>
<button type="submit">&lt;button type=submit&gt;</button>
<button type="button">&lt;button type=button&gt;</button>
<button type="reset">&lt;button type=reset&gt;</button>
<button type="button" disabled>&lt;button disabled&gt;</button>
</p>
</fieldset>
<p><a href="#top">Top</a></p>
</form>
</section>
</main>
<footer>
<p>
Made by <a href="http://twitter.com/cbracco">@cbracco</a>. Code on <a
href="http://github.com/cbracco/html5-test-page">GitHub</a
>.
</p>
</footer>
</div>
</body>
</html>

View file

@ -4,142 +4,8 @@ import Layout from "@layouts/BaseLayout.astro";
<Layout> <Layout>
<title slot="head">Home</title> <title slot="head">Home</title>
<style>
:root {
--scroll-multiplier: 5;
--theme: winternight;
}
.parallax-theme-winternight {
--layer-0-speed: 6250s;
--layer-1-speed: 1250s;
--layer-2-speed: 500s;
--layer-3-speed: 250s;
--layer-4-speed: 80s;
--layer-0-url: url("/parallax/winternight/0-sky.png");
--layer-1-url: url("/parallax/winternight/1-backmountain.png");
--layer-2-url: url("/parallax/winternight/2-midmountain.png");
--layer-3-url: url("/parallax/winternight/3-midforest.png");
--layer-4-url: url("/parallax/winternight/4-frontfloor.png");
--parallax-width: calc(3800px * 10);
}
.parallax-theme-sunnyvale-forest {
--layer-0-speed: 2000s;
--layer-1-speed: 400s;
--layer-2-speed: 50s;
--layer-0-url: url("/parallax/sunnyvale-forest/0-clouds.png");
--layer-1-url: url("/parallax/sunnyvale-forest/1-mountains.png");
--layer-2-url: url("/parallax/sunnyvale-forest/2-trees.png");
--parallax-width: calc(160px * 200);
}
.parallax-theme-city-destroyed {
--layer-0-speed: 1000s;
--layer-1-speed: 275s;
--layer-2-speed: 250s;
--layer-3-speed: 250s;
--layer-4-speed: 250s;
--layer-5-speed: 100s;
--layer-0-url: url("/parallax/city-destroyed/0-sky.png");
--layer-1-url: url("/parallax/city-destroyed/1-buildingssmoke.png");
--layer-2-url: url("/parallax/city-destroyed/2-water.png");
--layer-3-url: url("/parallax/city-destroyed/3-buildings.png");
--layer-4-url: url("/parallax/city-destroyed/4-buildingreflection.png");
--layer-5-url: url("/parallax/city-destroyed/5-frontsmoke.png");
--parallax-width: calc(3800px * 10);
}
.parallax-theme-city-destroyed .layer.layer-1,
.parallax-theme-city-destroyed .layer.layer-3,
.parallax-theme-city-destroyed .layer.layer-4 {
background-repeat: repeat-x;
}
.parallax-theme-city-destroyed .layer.layer-4 {
background-position-y: 16rem;
}
.parallax-container {
position: relative;
height: 30rem;
width: 100%;
overflow: hidden;
z-index: 0;
}
.layer {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: var(--parallax-width);
background-repeat: round;
background-position: bottom;
background-size: contain;
}
.layer-0 {
background-image: var(--layer-0-url);
z-index: 1;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-0-speed))
linear infinite;
}
.layer-1 {
background-image: var(--layer-1-url);
z-index: 2;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-1-speed))
linear infinite;
}
.layer-2 {
background-image: var(--layer-2-url);
z-index: 3;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-2-speed))
linear infinite;
}
.layer-3 {
background-image: var(--layer-3-url);
z-index: 4;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-3-speed))
linear infinite;
}
.layer-4 {
background-image: var(--layer-4-url);
z-index: 5;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-4-speed))
linear infinite;
}
.layer-5 {
background-image: var(--layer-5-url);
z-index: 6;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-5-speed))
linear infinite;
}
@keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
</style>
<Fragment slot="content"> <Fragment slot="content">
<article id="hero"> <article id="hero">
<div class="parallax-container" :class="'parallax-theme-' + theme">
<div class="layer layer-0"></div>
<div class="layer layer-1"></div>
<div class="layer layer-2"></div>
<div class="layer layer-3"></div>
<div class="layer layer-4"></div>
<div class="layer layer-5"></div>
</div>
<h2>Under Construction</h2> <h2>Under Construction</h2>
<p>Pardon the dust!</p> <p>Pardon the dust!</p>
</article> </article>

152
src/pages/parallax.astro Normal file
View file

@ -0,0 +1,152 @@
---
import Layout from "@layouts/BaseLayout.astro";
---
<Layout>
<title slot="head">Parallax Demo</title>
<style>
:root {
--scroll-multiplier: 5;
--theme: winternight;
}
.parallax-theme-winternight {
--layer-0-speed: 6250s;
--layer-1-speed: 1250s;
--layer-2-speed: 500s;
--layer-3-speed: 250s;
--layer-4-speed: 80s;
--layer-0-url: url("/parallax/winternight/0-sky.png");
--layer-1-url: url("/parallax/winternight/1-backmountain.png");
--layer-2-url: url("/parallax/winternight/2-midmountain.png");
--layer-3-url: url("/parallax/winternight/3-midforest.png");
--layer-4-url: url("/parallax/winternight/4-frontfloor.png");
--parallax-width: calc(3800px * 10);
}
.parallax-theme-sunnyvale-forest {
--layer-0-speed: 2000s;
--layer-1-speed: 400s;
--layer-2-speed: 50s;
--layer-0-url: url("/parallax/sunnyvale-forest/0-clouds.png");
--layer-1-url: url("/parallax/sunnyvale-forest/1-mountains.png");
--layer-2-url: url("/parallax/sunnyvale-forest/2-trees.png");
--parallax-width: calc(160px * 200);
}
.parallax-theme-city-destroyed {
--layer-0-speed: 1000s;
--layer-1-speed: 275s;
--layer-2-speed: 250s;
--layer-3-speed: 250s;
--layer-4-speed: 250s;
--layer-5-speed: 100s;
--layer-0-url: url("/parallax/city-destroyed/0-sky.png");
--layer-1-url: url("/parallax/city-destroyed/1-buildingssmoke.png");
--layer-2-url: url("/parallax/city-destroyed/2-water.png");
--layer-3-url: url("/parallax/city-destroyed/3-buildings.png");
--layer-4-url: url("/parallax/city-destroyed/4-buildingreflection.png");
--layer-5-url: url("/parallax/city-destroyed/5-frontsmoke.png");
--parallax-width: calc(3800px * 10);
}
.parallax-theme-city-destroyed .layer.layer-1,
.parallax-theme-city-destroyed .layer.layer-3,
.parallax-theme-city-destroyed .layer.layer-4 {
background-repeat: repeat-x;
}
.parallax-theme-city-destroyed .layer.layer-4 {
background-position-y: 16rem;
}
.parallax-container {
position: relative;
height: 30rem;
width: 100%;
overflow: hidden;
z-index: 0;
}
.layer {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: var(--parallax-width);
background-repeat: round;
background-position: bottom;
background-size: contain;
}
.layer-0 {
background-image: var(--layer-0-url);
z-index: 1;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-0-speed))
linear infinite;
}
.layer-1 {
background-image: var(--layer-1-url);
z-index: 2;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-1-speed))
linear infinite;
}
.layer-2 {
background-image: var(--layer-2-url);
z-index: 3;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-2-speed))
linear infinite;
}
.layer-3 {
background-image: var(--layer-3-url);
z-index: 4;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-3-speed))
linear infinite;
}
.layer-4 {
background-image: var(--layer-4-url);
z-index: 5;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-4-speed))
linear infinite;
}
.layer-5 {
background-image: var(--layer-5-url);
z-index: 6;
animation: scroll calc(var(--scroll-multiplier) * var(--layer-5-speed))
linear infinite;
}
@keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
</style>
<Fragment slot="content">
<article id="hero">
<div class="parallax-container" :class="'parallax-theme-' + theme">
<div class="layer layer-0"></div>
<div class="layer layer-1"></div>
<div class="layer layer-2"></div>
<div class="layer layer-3"></div>
<div class="layer layer-4"></div>
<div class="layer layer-5"></div>
</div>
<h2>Parallax Demo</h2>
<p>Pardon the dust!</p>
<select id="theme" x-model="theme">
<option value="winternight">Winternight</option>
<option value="sunnyvale-forest">SunnyVale</option>
<option value="city-destroyed">Apocalypse</option>
</select>
</article>
</Fragment>
</Layout>