Skip to content

Commit e820798

Browse files
Update to v2.
1 parent ca9d365 commit e820798

3 files changed

Lines changed: 547 additions & 84 deletions

File tree

index.html

Lines changed: 85 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,103 @@
11
<!DOCTYPE html>
2-
<html lang="en" >
2+
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta name="description" content="Browse CSS gradients by Bold Outlook. Search visually appealing gradients, preview each design, and copy ready-to-use CSS code.">
7+
<meta name="robots" content="index,follow">
8+
<meta name="theme-color" content="#5caf47">
9+
<meta property="og:type" content="website">
10+
<meta property="og:title" content="CSS Gradients by Bold Outlook">
11+
<meta property="og:description" content="A polished CSS gradient library with quick preview, search, and one-click copy.">
12+
<meta property="og:url" content="https://css-gradients.boldoutlook.com/">
13+
<meta property="og:image" content="https://www.boldoutlook.com/content/images/size/w1200/2025/06/Bold-Outlook-Favicon.png">
14+
<meta name="twitter:card" content="summary_large_image">
15+
<meta name="twitter:title" content="CSS Gradients by Bold Outlook">
16+
<meta name="twitter:description" content="Search, preview, and copy CSS gradients in a cleaner, more visual experience.">
17+
<link rel="canonical" href="https://css-gradients.boldoutlook.com/">
518
<link rel="icon" href="https://www.boldoutlook.com/content/images/size/w256h256/2025/06/Bold-Outlook-Favicon.png" type="image/png">
6-
<title>CSS Gradients</title>
19+
<title>CSS Gradients by Bold Outlook</title>
720
<link rel="stylesheet" href="./style.css">
8-
<!-- Google tag (gtag.js) -->
21+
<script type="application/ld+json">
22+
{
23+
"@context": "https://schema.org",
24+
"@type": "CollectionPage",
25+
"name": "CSS Gradients by Bold Outlook",
26+
"description": "A searchable collection of CSS gradients with visual previews and copy-ready CSS.",
27+
"url": "https://css-gradients.boldoutlook.com/",
28+
"publisher": {
29+
"@type": "Organization",
30+
"name": "Bold Outlook",
31+
"url": "https://www.boldoutlook.com/"
32+
}
33+
}
34+
</script>
935
<script async src="https://www.googletagmanager.com/gtag/js?id=G-X1B0Q53PK1"></script>
1036
<script>
1137
window.dataLayer = window.dataLayer || [];
1238
function gtag(){dataLayer.push(arguments);}
1339
gtag('js', new Date());
14-
1540
gtag('config', 'G-X1B0Q53PK1');
1641
</script>
17-
<!-- Google AdSense -->
18-
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2079625064533995"
19-
crossorigin="anonymous"></script>
42+
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2079625064533995" crossorigin="anonymous"></script>
2043
</head>
2144
<body>
22-
<header>
45+
<a class="skip-link" href="#main-content">Skip to content</a>
46+
47+
<header class="site-header">
48+
<div class="container hero">
49+
<div class="hero-copy">
50+
<p class="eyebrow"><a href="https://www.boldoutlook.com" title="Bold Outlook">Bold Outlook</a> resource</p>
2351
<h1>CSS Gradients</h1>
24-
<p>A collection of visually appealing gradients.</p>
25-
</header>
26-
<main>
27-
<section class="library" id="gradient-collection">
28-
<div class="gradient-grid" id="gradientGrid"></div>
29-
</section>
30-
</main>
31-
<footer>
32-
<p>&copy; 2024-2025 <a href="https://www.boldoutlook.com/">Bold Outlook</a>. All rights reserved.</p>
33-
</footer>
34-
<script src="./script.js"></script>
52+
<p class="hero-text">Explore a curated gradient library for interfaces, landing pages, backgrounds, and digital products. Preview each gradient instantly and copy production-ready CSS with one click.</p>
53+
<div class="hero-meta" aria-label="Library details">
54+
<span class="meta-pill"><strong id="gradient-total">0</strong> gradients</span>
55+
<span class="meta-pill">Ready-to-copy CSS</span>
56+
<span class="meta-pill">Search by hex or keyword</span>
57+
</div>
58+
</div>
59+
<aside class="hero-card">
60+
<h2>Quick tip</h2>
61+
<p>Use the search bar to find gradients by color code or gradient type, then copy the full CSS declaration directly into your project.</p>
62+
</aside>
63+
</div>
64+
</header>
65+
66+
<main id="main-content">
67+
<section class="controls-wrap">
68+
<div class="container controls" role="search" aria-label="Gradient search and filters">
69+
<label class="search-field" for="gradient-search">
70+
<span class="search-label">Search gradients</span>
71+
<input id="gradient-search" type="search" placeholder="Search by hex, linear-gradient, or color values" autocomplete="off">
72+
</label>
73+
<div class="toolbar-actions">
74+
<button id="clear-search" type="button" class="button">Clear</button>
75+
<button id="toggle-view" type="button" class="button" aria-pressed="false">Compact view</button>
76+
</div>
77+
</div>
78+
</section>
79+
80+
<section class="container results-bar" aria-live="polite">
81+
<p id="results-count">Showing 0 gradients</p>
82+
</section>
83+
84+
<section class="container library-section">
85+
<div id="empty-state" class="empty-state" hidden>
86+
<h2>No gradients found</h2>
87+
<p>Try a different hex code or clear the search to browse the full collection.</p>
88+
</div>
89+
<div class="gradient-grid" id="gradientGrid" aria-label="CSS gradient library"></div>
90+
</section>
91+
</main>
92+
93+
<footer class="site-footer">
94+
<div class="container footer-inner">
95+
<p>CSS Gradients by <a href="https://www.boldoutlook.com/">Bold Outlook</a>.</p>
96+
<p class="footer-note"></p>
97+
</div>
98+
</footer>
3599

100+
<div id="copied-alert" class="alert-box" role="status" aria-live="polite" hidden></div>
101+
<script src="./script.js"></script>
36102
</body>
37103
</html>

script.js

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -100,30 +100,100 @@ document.addEventListener("DOMContentLoaded", function() {
100100
];
101101

102102
const gradientGrid = document.getElementById("gradientGrid");
103+
const gradientSearch = document.getElementById("gradient-search");
104+
const clearSearchButton = document.getElementById("clear-search");
105+
const toggleViewButton = document.getElementById("toggle-view");
106+
const resultsCount = document.getElementById("results-count");
107+
const gradientTotal = document.getElementById("gradient-total");
108+
const emptyState = document.getElementById("empty-state");
109+
const copiedAlert = document.getElementById("copied-alert");
103110

104-
gradients.forEach(gradient => {
105-
const gradientBox = document.createElement("div");
106-
gradientBox.classList.add("gradient-box");
107-
gradientBox.style.background = gradient;
108-
gradientBox.addEventListener("click", () => {
109-
navigator.clipboard.writeText(`background: ${gradient};`).then(() => {
110-
showAlert("Gradient CSS copied to clipboard!");
111-
});
112-
});
113-
gradientGrid.appendChild(gradientBox);
114-
});
111+
gradientTotal.textContent = gradients.length;
115112

116-
function showAlert(message) {
117-
let alertBox = document.querySelector(".alert-box");
118-
if (!alertBox) {
119-
alertBox = document.createElement("div");
120-
alertBox.classList.add("alert-box");
121-
document.body.appendChild(alertBox);
113+
function getGradientType(gradient) {
114+
const colorCount = (gradient.match(/#/g) || []).length;
115+
return colorCount >= 3 ? "3-color gradient" : "2-color gradient";
116+
}
117+
118+
function buildGradientCard(gradient, index) {
119+
const gradientType = getGradientType(gradient);
120+
const cssDeclaration = `background: ${gradient};`;
121+
122+
return `
123+
<article class="gradient-card" data-gradient="${gradient.toLowerCase()}">
124+
<button class="gradient-preview" type="button" style="background:${gradient};" data-copy="${cssDeclaration}" aria-label="Copy CSS for gradient ${index + 1}"></button>
125+
<div class="card-body">
126+
<span class="gradient-badge">Gradient ${index + 1}</span>
127+
<h2 class="gradient-title">${gradientType}</h2>
128+
<p class="gradient-meta">Click the preview or button below to copy the full CSS declaration.</p>
129+
<pre class="code-block"><code>${cssDeclaration}</code></pre>
130+
<div class="card-actions">
131+
<span class="gradient-index">#${String(index + 1).padStart(3, "0")}</span>
132+
<button class="copy-button" type="button" data-copy="${cssDeclaration}">Copy CSS</button>
133+
</div>
134+
</div>
135+
</article>
136+
`;
137+
}
138+
139+
function renderGradients() {
140+
const query = gradientSearch.value.trim().toLowerCase();
141+
const filtered = gradients
142+
.map((gradient, index) => ({ gradient, index }))
143+
.filter(({ gradient }) => gradient.toLowerCase().includes(query));
144+
145+
gradientGrid.innerHTML = filtered
146+
.map(({ gradient, index }) => buildGradientCard(gradient, index))
147+
.join("");
148+
149+
resultsCount.textContent = `Showing ${filtered.length} ${filtered.length === 1 ? "gradient" : "gradients"}`;
150+
emptyState.hidden = filtered.length !== 0;
151+
}
152+
153+
async function copyToClipboard(text) {
154+
try {
155+
await navigator.clipboard.writeText(text);
156+
} catch (error) {
157+
const helper = document.createElement("textarea");
158+
helper.value = text;
159+
document.body.appendChild(helper);
160+
helper.select();
161+
document.execCommand("copy");
162+
document.body.removeChild(helper);
122163
}
123-
alertBox.textContent = message;
124-
alertBox.classList.add("show");
125-
setTimeout(() => {
126-
alertBox.classList.remove("show");
127-
}, 2000);
128164
}
165+
166+
function showAlert(message) {
167+
copiedAlert.textContent = message;
168+
copiedAlert.hidden = false;
169+
window.clearTimeout(showAlert.timeoutId);
170+
showAlert.timeoutId = window.setTimeout(() => {
171+
copiedAlert.hidden = true;
172+
}, 2200);
173+
}
174+
175+
gradientSearch.addEventListener("input", renderGradients);
176+
177+
clearSearchButton.addEventListener("click", () => {
178+
gradientSearch.value = "";
179+
renderGradients();
180+
gradientSearch.focus();
181+
});
182+
183+
toggleViewButton.addEventListener("click", () => {
184+
const isCompact = document.body.classList.toggle("compact-view");
185+
toggleViewButton.setAttribute("aria-pressed", String(isCompact));
186+
toggleViewButton.textContent = isCompact ? "Expanded view" : "Compact view";
187+
});
188+
189+
gradientGrid.addEventListener("click", async (event) => {
190+
const target = event.target.closest("[data-copy]");
191+
if (!target) return;
192+
193+
const cssValue = target.dataset.copy;
194+
await copyToClipboard(cssValue);
195+
showAlert("Gradient CSS copied to clipboard.");
196+
});
197+
198+
renderGradients();
129199
});

0 commit comments

Comments
 (0)