Optimize: drop Bootstrap CDN, add caching headers & image hints
Performance / self-hosting - Remove the render-blocking Bootstrap 4 CDN stylesheet (~160 KB + extra DNS/TLS to a third party) and replace it with ~60 lines of self-hosted grid/utility CSS covering the small subset actually used (container, row, col-lg-5/6/7, order-lg, align-items-center, text-center, table-responsive, spacing, and the button base). Verified across desktop/tablet/mobile. - Add a Cloudflare Pages `_headers` file: 30-day cache for static media and icons, 1-day for css/js, plus baseline security headers (X-Content-Type-Options, Referrer-Policy). - Add decoding="async" to all lazily-loaded images. The site now loads no third-party CSS; only Google Fonts remain external. SCSS source kept in sync (new components/_grid partial; button base + reset mirrored in main.scss). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
49
css/components/_grid.scss
Normal file
49
css/components/_grid.scss
Normal file
@@ -0,0 +1,49 @@
|
||||
// Minimal grid & utilities — self-hosted replacement for the small subset of
|
||||
// Bootstrap 4 this site used. Removes a render-blocking ~160 KB external
|
||||
// stylesheet. Breakpoint lg = 992px (one past $m-break: 991px).
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1140px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
|
||||
> [class*="col-"] {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// mobile-first: columns are full width until the lg breakpoint
|
||||
[class*="col-lg-"] { flex: 0 0 100%; max-width: 100%; }
|
||||
|
||||
.align-items-center { align-items: center; }
|
||||
.text-center { text-align: center; }
|
||||
.mb-4 { margin-bottom: 1.5rem; }
|
||||
|
||||
.table-responsive {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.col-lg-5 { flex: 0 0 41.6667%; max-width: 41.6667%; }
|
||||
.col-lg-6 { flex: 0 0 50%; max-width: 50%; }
|
||||
.col-lg-7 { flex: 0 0 58.3333%; max-width: 58.3333%; }
|
||||
.order-lg-1 { order: 1; }
|
||||
.order-lg-2 { order: 2; }
|
||||
.mb-lg-0 { margin-bottom: 0; }
|
||||
}
|
||||
72
css/main.css
72
css/main.css
@@ -34,9 +34,71 @@ html { scroll-behavior: smooth; }
|
||||
p, a, li, span, div, td, th { font-family: "Lato", sans-serif; }
|
||||
h1, h2, h3, h4, h5, h6 { font-family: "Libre Baskerville", serif; }
|
||||
|
||||
img { max-width: 100%; }
|
||||
img { max-width: 100%; vertical-align: middle; }
|
||||
h1, h2, h3, h4, h5, h6 { margin-top: 0; }
|
||||
p { margin-top: 0; margin-bottom: 1rem; }
|
||||
|
||||
/* ============================================================
|
||||
MINIMAL GRID & UTILITIES
|
||||
Self-hosted replacement for the small subset of Bootstrap 4
|
||||
this site used (grid, a few utilities, button base). Removes a
|
||||
render-blocking ~160 KB external stylesheet. Breakpoint lg = 992px.
|
||||
============================================================ */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1140px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
.row > [class*="col-"] {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
/* mobile-first: columns are full width until the lg breakpoint */
|
||||
[class*="col-lg-"] { flex: 0 0 100%; max-width: 100%; }
|
||||
|
||||
.align-items-center { align-items: center; }
|
||||
.text-center { text-align: center; }
|
||||
|
||||
.mb-4 { margin-bottom: 1.5rem; }
|
||||
|
||||
.table-responsive {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.col-lg-5 { flex: 0 0 41.6667%; max-width: 41.6667%; }
|
||||
.col-lg-6 { flex: 0 0 50%; max-width: 50%; }
|
||||
.col-lg-7 { flex: 0 0 58.3333%; max-width: 58.3333%; }
|
||||
.order-lg-1 { order: 1; }
|
||||
.order-lg-2 { order: 2; }
|
||||
.mb-lg-0 { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
/* ---------- Buttons ---------- */
|
||||
.btn {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
border: 1px solid transparent;
|
||||
line-height: 1.5;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
}
|
||||
.btn {
|
||||
font-family: "Libre Baskerville", serif;
|
||||
font-size: 14px;
|
||||
@@ -46,10 +108,18 @@ img { max-width: 100%; }
|
||||
}
|
||||
.btn + .btn { margin-left: 0.5rem; }
|
||||
|
||||
.btn-light {
|
||||
color: #212529;
|
||||
background-color: #f8f9fa;
|
||||
border-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: var(--white);
|
||||
background-color: var(--gold);
|
||||
border-color: var(--gold);
|
||||
}
|
||||
.btn-primary:hover { color: var(--white); }
|
||||
.btn-primary:hover {
|
||||
background-color: var(--gold-dark);
|
||||
border-color: var(--gold-dark);
|
||||
|
||||
@@ -22,9 +22,19 @@ $l-break: 1199px;
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
@import 'components/grid';
|
||||
|
||||
//btns
|
||||
.btn {
|
||||
@include Libre;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
border: 1px solid transparent;
|
||||
line-height: 1.5;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.3px;
|
||||
padding: 0.55rem 1.5rem;
|
||||
@@ -33,10 +43,19 @@ $l-break: 1199px;
|
||||
& + .btn { margin-left: 0.5rem; }
|
||||
}
|
||||
|
||||
.btn-light {
|
||||
color: #212529;
|
||||
background-color: #f8f9fa;
|
||||
border-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: $white;
|
||||
background-color: $gold;
|
||||
border-color: $gold;
|
||||
|
||||
&:hover { color: $white; }
|
||||
|
||||
&:hover {
|
||||
background-color: darken($gold, 10%);
|
||||
border-color: darken($gold, 10%);
|
||||
@@ -73,9 +92,12 @@ p, a, li, span, div, td, th {
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
@include Libre;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
img { max-width: 100%; }
|
||||
p { margin-top: 0; margin-bottom: 1rem; }
|
||||
|
||||
img { max-width: 100%; vertical-align: middle; }
|
||||
|
||||
.page-content {
|
||||
padding-top: 92px;
|
||||
|
||||
Reference in New Issue
Block a user