From 89c725a282b2860968997bd82de9323f1c9a81ca Mon Sep 17 00:00:00 2001 From: Keith Solomon Date: Sat, 24 May 2025 12:22:24 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feature:=20Set=20up=20basic=20layout?= =?UTF-8?q?=20and=20styles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/stylesheets/style.css | 261 ++++++++++++++++++++++++++++++----- styles/base.css | 13 +- styles/colors.css | 41 ++++++ styles/typography.css | 150 ++++++++++++++++++++ views/footer.ejs | 16 +++ views/header.ejs | 32 +++++ views/index.ejs | 20 ++- 7 files changed, 475 insertions(+), 58 deletions(-) create mode 100644 styles/colors.css create mode 100644 styles/typography.css create mode 100644 views/footer.ejs create mode 100644 views/header.ejs diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 29b0cf9..6b5ab6c 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -3,22 +3,36 @@ @layer theme, base, components, utilities; @layer theme { :root, :host { - --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-sans: "Raleway", sans-serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --color-blue-400: oklch(70.7% 0.165 254.624); --color-slate-900: oklch(20.8% 0.042 265.755); --color-gray-200: oklch(92.8% 0.006 264.531); + --color-gray-400: oklch(70.7% 0.022 261.325); --color-gray-800: oklch(27.8% 0.033 256.848); - --color-white: #fff; + --color-black: oklch(0% 0 0); + --color-white: oklch(100% 0 0); --spacing: 0.25rem; + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); --text-base: 1rem; --text-base--line-height: calc(1.5 / 1); - --text-4xl: 2.25rem; - --text-4xl--line-height: calc(2.5 / 2.25); + --radius-sm: 0.25rem; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); --default-font-family: var(--font-sans); --default-mono-font-family: var(--font-mono); + --color-primary: oklch(0.57 0.203362 257.1706); + --color-secondary: oklch(0.56 0.0176 257.23); + --color-bodylinks: oklch(0.48 0.0789 211.58); + --color-warning: oklch(84.42% 0.1722 84.93); + --h1: calc(var(--text-base) * 2.25); + --h2: calc(var(--text-base) * 1.75); + --h3: calc(var(--text-base) * 1.5); + --h4: calc(var(--text-base) * 1.25); + --h5: calc(var(--text-base) * 1.125); + --h6: calc(var(--text-base) * 1.05); } } @layer base { @@ -167,31 +181,109 @@ } } @layer utilities { - .my-2 { - margin-block: calc(var(--spacing) * 2); + .container { + width: 100%; + @media (width >= 40rem) { + max-width: 40rem; + } + @media (width >= 48rem) { + max-width: 48rem; + } + @media (width >= 64rem) { + max-width: 64rem; + } + @media (width >= 80rem) { + max-width: 80rem; + } + @media (width >= 96rem) { + max-width: 96rem; + } } - .my-4 { - margin-block: calc(var(--spacing) * 4); + .mx-auto { + margin-inline: auto; } - .mb-2 { - margin-bottom: calc(var(--spacing) * 2); + .mt-8 { + margin-top: calc(var(--spacing) * 8); + } + .mr-2 { + margin-right: calc(var(--spacing) * 2); + } + .mb-4 { + margin-bottom: calc(var(--spacing) * 4); + } + .flex { + display: flex; } .table { display: table; } + .h-8 { + height: calc(var(--spacing) * 8); + } + .w-full { + width: 100%; + } .border-collapse { border-collapse: collapse; } .resize { resize: both; } + .items-center { + align-items: center; + } + .justify-between { + justify-content: space-between; + } + .justify-center { + justify-content: center; + } + .gap-8 { + gap: calc(var(--spacing) * 8); + } + .space-x-4 { + :where(& > :not(:last-child)) { + --tw-space-x-reverse: 0; + margin-inline-start: calc(calc(var(--spacing) * 4) * var(--tw-space-x-reverse)); + margin-inline-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse))); + } + } .border { border-style: var(--tw-border-style); border-width: 1px; } - .text-4xl { - font-size: var(--text-4xl); - line-height: var(--tw-leading, var(--text-4xl--line-height)); + .bg-gray-200 { + background-color: var(--color-gray-200); + } + .bg-gray-800 { + background-color: var(--color-gray-800); + } + .p-4 { + padding: calc(var(--spacing) * 4); + } + .px-4 { + padding-inline: calc(var(--spacing) * 4); + } + .py-4 { + padding-block: calc(var(--spacing) * 4); + } + .py-8 { + padding-block: calc(var(--spacing) * 8); + } + .text-center { + text-align: center; + } + .text-blue-400 { + color: var(--color-blue-400); + } + .text-bodylinks { + color: var(--color-bodylinks); + } + .text-gray-800 { + color: var(--color-gray-800); + } + .text-white { + color: var(--color-white); } .underline { text-decoration-line: underline; @@ -200,35 +292,131 @@ outline-style: var(--tw-outline-style); outline-width: 1px; } + .transition { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .hover\:text-gray-400 { + &:hover { + @media (hover: hover) { + color: var(--color-gray-400); + } + } + } } body { - width: 100%; - @media (width >= 40rem) { - max-width: 40rem; - } - @media (width >= 48rem) { - max-width: 48rem; - } - @media (width >= 64rem) { - max-width: 64rem; - } - @media (width >= 80rem) { - max-width: 80rem; - } - @media (width >= 96rem) { - max-width: 96rem; - } - margin-inline: auto; background-color: var(--color-slate-900); - padding-inline: calc(var(--spacing) * 4); - padding-block: calc(var(--spacing) * 8); + font-family: var(--font-sans); font-size: var(--text-base); line-height: var(--tw-leading, var(--text-base--line-height)); color: var(--color-gray-200); - font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; } -a { - color: #00B7FF; +::selection { + background: var(--color-warning); +} +@layer components { + h1, h2, h3, h4, h5, h6 { + font-weight: 700; + margin: 0 0 1rem; + } + h1, .h1 { + font-size: var(--h1); + line-height: 1.2; + } + h2, .h2 { + font-size: var(--h2); + line-height: 1.3; + } + h3, .h3 { + font-size: var(--h3); + line-height: 1.4; + } + h4, .h4 { + font-size: var(--h4); + line-height: 1.5; + } + h5, .h5 { + font-size: var(--h5); + } + h6, .h6 { + font-size: var(--h6); + } +} +a, .link { + color: var(--color-bodylinks); + text-decoration: none; + transition: color 200ms; + cursor: pointer; + &:hover { + color: var(--color-primary); + } +} +h1 a, .h1 a, h2 a, .h2 a, h3 a, .h3 a { + color: inherit; + text-decoration: underline; +} +p { + margin-top: 0; + margin-bottom: 1rem; +} +li ul, li ol { + margin: 0 1rem; +} +ul { + list-style-type: disc; +} +ol { + list-style-type: decimal; +} +ol ol { + list-style: lower-alpha; +} +ol ol ol { + list-style: lower-roman; +} +ol ol ol ol { + list-style: lower-alpha; +} +pre, code, samp, style { + font-family: monospace; +} +pre { + font-size: 0.875rem; + overflow: auto; + padding: 1.5rem; +} +pre code { + background-color: inherit; + border-radius: 0; + color: inherit; + padding: 0; +} +code { + border-radius: var(--radius-sm); + background-color: color-mix(in srgb, oklch(0% 0 0) 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-black) 30%, transparent); + } + padding-inline: 3px; + padding-block: 2px; + font-family: var(--font-mono); + font-size: var(--text-xs); + line-height: var(--tw-leading, var(--text-xs--line-height)); + color: var(--color-black); +} +hr { + background-color: black; + border: none; + display: block; + height: 1px; + margin: 1rem 0; + width: 100%; +} +@property --tw-space-x-reverse { + syntax: "*"; + inherits: false; + initial-value: 0; } @property --tw-border-style { syntax: "*"; @@ -243,6 +431,7 @@ a { @layer properties { @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { *, ::before, ::after, ::backdrop { + --tw-space-x-reverse: 0; --tw-border-style: solid; --tw-outline-style: solid; } diff --git a/styles/base.css b/styles/base.css index 4d09857..5918ced 100644 --- a/styles/base.css +++ b/styles/base.css @@ -1,12 +1,5 @@ @import 'tailwindcss'; +@import './colors.css'; +@import './typography.css'; + @plugin "@tailwindcss/typography"; - -body { - @apply container mx-auto px-4 py-8 text-base text-gray-200 bg-slate-900; - - font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; -} - -a { - color: #00B7FF; -} diff --git a/styles/colors.css b/styles/colors.css new file mode 100644 index 0000000..73cd2e3 --- /dev/null +++ b/styles/colors.css @@ -0,0 +1,41 @@ +/* Theme color definitions */ + +@theme { + --color-black: oklch(0% 0 0); + --color-white: oklch(100% 0 0); + + --color-background: oklch(89.75% 0 0); + --color-text: var(--color-black); + + --color-primary: oklch(0.57 0.203362 257.1706); + --color-primary-100: color-mix(in oklch, var(--color-primary) 10%, white); + --color-primary-200: color-mix(in oklch, var(--color-primary) 20%, white); + --color-primary-300: color-mix(in oklch, var(--color-primary) 30%, white); + --color-primary-400: color-mix(in oklch, var(--color-primary) 40%, white); + --color-primary-500: color-mix(in oklch, var(--color-primary) 50%, white); + --color-primary-600: color-mix(in oklch, var(--color-primary) 60%, white); + --color-primary-700: color-mix(in oklch, var(--color-primary) 70%, white); + --color-primary-800: color-mix(in oklch, var(--color-primary) 80%, white); + --color-primary-900: color-mix(in oklch, var(--color-primary) 90%, white); + + --color-secondary: oklch(0.56 0.0176 257.23); + --color-secondary-100: color-mix(in oklch, var(--color-secondary) 10%, white); + --color-secondary-200: color-mix(in oklch, var(--color-secondary) 20%, white); + --color-secondary-300: color-mix(in oklch, var(--color-secondary) 30%, white); + --color-secondary-400: color-mix(in oklch, var(--color-secondary) 40%, white); + --color-secondary-500: color-mix(in oklch, var(--color-secondary) 50%, white); + --color-secondary-600: color-mix(in oklch, var(--color-secondary) 60%, white); + --color-secondary-700: color-mix(in oklch, var(--color-secondary) 70%, white); + --color-secondary-800: color-mix(in oklch, var(--color-secondary) 80%, white); + --color-secondary-900: color-mix(in oklch, var(--color-secondary) 90%, white); + + --color-bodylinks: oklch(0.48 0.0789 211.58); + --color-footlinks: oklch(0.65 0.1104 212.2); + + --color-success: oklch(64.01% 0.1751 146.7); + --color-info: oklch(0.55 0.0922 211.57); + --color-warning: oklch(84.42% 0.1722 84.93); + --color-danger: oklch(0.5126 0.1865 22.61); + --color-light: oklch(98.16% 0.0017 247.8); + --color-dark: oklch(34.51% 0.0133 248.2); +} diff --git a/styles/typography.css b/styles/typography.css new file mode 100644 index 0000000..cc3beca --- /dev/null +++ b/styles/typography.css @@ -0,0 +1,150 @@ +/* Basic typographical styles */ + +/** + * All font sizes are based on 16px base font size and 1920px wide screen + * Default size is expressed as percentage of screen width. + * text-14px: 12px-27px, default: 14px + * text-16px: 14px-28px, default: 16px + * text-18px: 14px-30px, default: 18px + * text-20px: 16px-32px, default: 20px + * text-22px: 17px-33px, default: 22px + * text-25px: 18px-35px, default: 25px + * text-30px: 19px-37px, default: 30px + * text-35px: 20px-40px, default: 35px + * text-38px: 22px-48px, default: 38px + * text-40px: 24px-56px, default: 40px + * text-45px: 25px-64px, default: 45px + * text-50px: 27px-72px, default: 50px + * text-55px: 28px-76px, default: 55px + * text-60px: 30px-80px, default: 60px + * text-70px: 30px-76px, default: 70px + * text-75px: 32px-80px, default: 75px +*/ + +@theme { + --font-sans: "Raleway", sans-serif; + --line-height: 1.6; + + --text-base: 1rem; + --text-14px: clamp(0.75rem, 0.7292vw, 1.7rem); + --text-16px: clamp(0.875rem, 0.8333vw, 1.8rem); + --text-18px: clamp(0.875rem, 0.9375vw, 1.9rem); + --text-20px: clamp(1rem, 1.0417vw, 2rem); + --text-22px: clamp(1.1rem, 1.15vw, 2.1rem); + --text-25px: clamp(1.125rem, 1.3021vw, 2.2rem); + --text-30px: clamp(1.185rem, 1.5625vw, 2.35rem); + --text-35px: clamp(1.25rem, 1.8229vw, 2.5rem); + --text-38px: clamp(1.4rem, 1.9791vw, 3rem); + --text-40px: clamp(1.5rem, 2.0834vw, 3.5rem); + --text-45px: clamp(1.6rem, 2.3438vw, 4rem); + --text-50px: clamp(1.7rem, 2.6042vw, 4.5rem); + --text-70px: clamp(1.9rem, 3.6458vw, 4.8rem); + --text-75px: clamp(2rem, 3.9063vw, 5rem); + + --h1: calc(var(--text-base) * 2.25); + --h2: calc(var(--text-base) * 1.75); + --h3: calc(var(--text-base) * 1.5); + --h4: calc(var(--text-base) * 1.25); + --h5: calc(var(--text-base) * 1.125); + --h6: calc(var(--text-base) * 1.05); +} + +body { + @apply font-sans text-base text-gray-200 bg-slate-900; +} + +::selection { background: var(--color-warning); } + +@layer components { + h1, h2, h3, + h4, h5, h6 { + font-weight: 700; + margin: 0 0 1rem; + } + + h1, .h1 { + font-size: var(--h1); + line-height: 1.2; + } + + h2, .h2 { + font-size: var(--h2); + line-height: 1.3; + } + + h3, .h3 { + font-size: var(--h3); + line-height: 1.4; + } + + h4, .h4 { + font-size: var(--h4); + line-height: 1.5; + } + + h5, .h5 { font-size: var(--h5); } + + h6, .h6 { font-size: var(--h6); } +} + +a, .link { + color: var(--color-bodylinks); + text-decoration: none; + transition: color 200ms; + cursor: pointer; + + &:hover { color: var(--color-primary); } +} + +h1 a, .h1 a, +h2 a, .h2 a, +h3 a, .h3 a { + color: inherit; + text-decoration: underline; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +li ul, li ol { margin: 0 1rem; } + +ul { list-style-type: disc; } + +ol { list-style-type: decimal; } + +ol ol { list-style: lower-alpha; } + +ol ol ol { list-style: lower-roman; } + +ol ol ol ol { list-style: lower-alpha; } + +pre, code, +samp, style { font-family: monospace; } + +pre { + font-size: 0.875rem; + overflow: auto; + padding: 1.5rem; +} + +pre code { + background-color: inherit; + border-radius: 0; + color: inherit; + padding: 0; +} + +code { + @apply bg-black/30 px-[3px] py-[2px] font-mono text-black text-xs rounded-sm; +} + +hr { + background-color: black; + border: none; + display: block; + height: 1px; + margin: 1rem 0; + width: 100%; +} diff --git a/views/footer.ejs b/views/footer.ejs new file mode 100644 index 0000000..9b70339 --- /dev/null +++ b/views/footer.ejs @@ -0,0 +1,16 @@ + + + + diff --git a/views/header.ejs b/views/header.ejs new file mode 100644 index 0000000..77bfc1a --- /dev/null +++ b/views/header.ejs @@ -0,0 +1,32 @@ + + + + + + + + + + <%= title %> + + + + + + +
+
+
+
+ +

<%= title %>

+
+ +
+
diff --git a/views/index.ejs b/views/index.ejs index 31c34dd..4c7430c 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -1,12 +1,8 @@ - - - - <%= title %> - - - -

<%= title %>

-
-

Welcome to <%= title %>

- - +<%- include('header'); -%> + +
+

Welcome to the <%= title %> EJS Template

+

This is a simple example of using EJS for templating.

+
+ +<%- include('footer'); -%>