Skip to content

Commit 61bc989

Browse files
maxmax
authored andcommitted
CSS Gradient Generator - initial release
0 parents  commit 61bc989

1 file changed

Lines changed: 208 additions & 0 deletions

File tree

index.html

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>CSS Gradient Generator - Create Beautiful Gradients</title>
7+
<meta name="description" content="Free online CSS gradient generator. Create linear, radial, and conic gradients with real-time preview. Copy CSS code instantly.">
8+
<meta name="keywords" content="CSS gradient, gradient generator, linear gradient, radial gradient, conic gradient, CSS tool">
9+
<meta property="og:title" content="CSS Gradient Generator">
10+
<meta property="og:description" content="Create beautiful CSS gradients with real-time preview. Linear, radial, and conic gradients.">
11+
<meta property="og:type" content="website">
12+
<link rel="canonical" href="https://maxmini0214.github.io/css-gradient/">
13+
<style>
14+
*{margin:0;padding:0;box-sizing:border-box}
15+
:root{--bg:#0f0f13;--surface:#1a1a24;--surface2:#252535;--border:#333348;--text:#e8e8f0;--text2:#9999b0;--accent:#7c6cf0;--accent2:#f06c9b}
16+
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:var(--bg);color:var(--text);min-height:100vh}
17+
header{text-align:center;padding:2rem 1rem 1rem}
18+
header h1{font-size:1.8rem;background:linear-gradient(135deg,var(--accent),var(--accent2));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
19+
header p{color:var(--text2);margin-top:.4rem;font-size:.95rem}
20+
.app{max-width:1100px;margin:0 auto;padding:1rem;display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}
21+
@media(max-width:768px){.app{grid-template-columns:1fr}}
22+
.preview-card{background:var(--surface);border-radius:16px;padding:1.5rem;border:1px solid var(--border)}
23+
.preview-box{width:100%;aspect-ratio:4/3;border-radius:12px;transition:background .3s}
24+
.controls-card{background:var(--surface);border-radius:16px;padding:1.5rem;border:1px solid var(--border);display:flex;flex-direction:column;gap:1.2rem}
25+
label{font-size:.85rem;color:var(--text2);display:block;margin-bottom:.4rem}
26+
.type-btns{display:flex;gap:.5rem}
27+
.type-btns button{flex:1;padding:.6rem;border:1px solid var(--border);background:var(--surface2);color:var(--text);border-radius:8px;cursor:pointer;font-size:.85rem;transition:all .2s}
28+
.type-btns button.active{background:var(--accent);border-color:var(--accent);color:#fff}
29+
.color-stops{display:flex;flex-direction:column;gap:.6rem}
30+
.color-row{display:flex;align-items:center;gap:.6rem}
31+
.color-row input[type=color]{width:44px;height:36px;border:none;border-radius:8px;cursor:pointer;background:none}
32+
.color-row input[type=range]{flex:1}
33+
.color-row .pos{font-size:.8rem;color:var(--text2);width:36px;text-align:right}
34+
.color-row button{background:none;border:none;color:var(--text2);cursor:pointer;font-size:1.1rem;padding:0 .3rem}
35+
.color-row button:hover{color:var(--accent2)}
36+
.add-color{background:var(--surface2);border:1px dashed var(--border);color:var(--text2);padding:.5rem;border-radius:8px;cursor:pointer;font-size:.85rem}
37+
.add-color:hover{border-color:var(--accent);color:var(--accent)}
38+
.angle-group{display:flex;align-items:center;gap:.8rem}
39+
.angle-group input[type=range]{flex:1}
40+
.angle-group span{font-size:.9rem;width:45px;text-align:right}
41+
.code-box{background:var(--bg);border-radius:10px;padding:1rem;font-family:'SF Mono',Consolas,monospace;font-size:.82rem;color:var(--accent);word-break:break-all;line-height:1.5;position:relative;border:1px solid var(--border)}
42+
.copy-btn{position:absolute;top:.6rem;right:.6rem;background:var(--accent);color:#fff;border:none;padding:.4rem .8rem;border-radius:6px;cursor:pointer;font-size:.8rem;transition:background .2s}
43+
.copy-btn:hover{background:var(--accent2)}
44+
.copy-btn.copied{background:#2ea043}
45+
.presets{margin-top:.5rem}
46+
.presets h3{font-size:.9rem;color:var(--text2);margin-bottom:.6rem}
47+
.preset-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:.5rem}
48+
@media(max-width:768px){.preset-grid{grid-template-columns:repeat(5,1fr)}}
49+
.preset-swatch{aspect-ratio:1;border-radius:10px;cursor:pointer;border:2px solid transparent;transition:border .2s}
50+
.preset-swatch:hover{border-color:var(--accent)}
51+
footer{text-align:center;padding:2rem 1rem;color:var(--text2);font-size:.8rem}
52+
input[type=range]{-webkit-appearance:none;background:var(--surface2);height:6px;border-radius:3px;outline:none}
53+
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:var(--accent);cursor:pointer}
54+
</style>
55+
</head>
56+
<body>
57+
<header>
58+
<h1>CSS Gradient Generator</h1>
59+
<p>Create beautiful gradients — copy the CSS instantly</p>
60+
</header>
61+
62+
<div class="app">
63+
<div class="preview-card">
64+
<div class="preview-box" id="preview"></div>
65+
<div class="code-box" id="codeBox" style="margin-top:1rem">
66+
<button class="copy-btn" id="copyBtn" onclick="copyCSS()">Copy</button>
67+
<code id="codeText"></code>
68+
</div>
69+
</div>
70+
71+
<div class="controls-card">
72+
<div>
73+
<label>Gradient Type</label>
74+
<div class="type-btns" id="typeBtns">
75+
<button class="active" data-type="linear">Linear</button>
76+
<button data-type="radial">Radial</button>
77+
<button data-type="conic">Conic</button>
78+
</div>
79+
</div>
80+
81+
<div id="angleGroup">
82+
<label>Angle</label>
83+
<div class="angle-group">
84+
<input type="range" id="angle" min="0" max="360" value="135">
85+
<span id="angleVal">135°</span>
86+
</div>
87+
</div>
88+
89+
<div>
90+
<label>Color Stops</label>
91+
<div class="color-stops" id="colorStops"></div>
92+
<button class="add-color" id="addColor" onclick="addStop()">+ Add Color</button>
93+
</div>
94+
95+
<div class="presets">
96+
<h3>Presets</h3>
97+
<div class="preset-grid" id="presetGrid"></div>
98+
</div>
99+
</div>
100+
</div>
101+
102+
<footer>Built with ♥ — No frameworks, no tracking, just gradients.</footer>
103+
104+
<script>
105+
const PRESETS=[
106+
{type:'linear',angle:135,stops:[{c:'#667eea',p:0},{c:'#764ba2',p:100}]},
107+
{type:'linear',angle:120,stops:[{c:'#f093fb',p:0},{c:'#f5576c',p:100}]},
108+
{type:'linear',angle:135,stops:[{c:'#4facfe',p:0},{c:'#00f2fe',p:100}]},
109+
{type:'linear',angle:135,stops:[{c:'#43e97b',p:0},{c:'#38f9d7',p:100}]},
110+
{type:'linear',angle:135,stops:[{c:'#fa709a',p:0},{c:'#fee140',p:100}]},
111+
{type:'linear',angle:135,stops:[{c:'#a18cd1',p:0},{c:'#fbc2eb',p:100}]},
112+
{type:'radial',angle:0,stops:[{c:'#ffecd2',p:0},{c:'#fcb69f',p:100}]},
113+
{type:'conic',angle:0,stops:[{c:'#ff9a9e',p:0},{c:'#fad0c4',p:50},{c:'#ff9a9e',p:100}]},
114+
{type:'linear',angle:90,stops:[{c:'#0c0c1d',p:0},{c:'#1a1a40',p:50},{c:'#4a00e0',p:100}]},
115+
{type:'linear',angle:135,stops:[{c:'#ff0844',p:0},{c:'#ffb199',p:100}]},
116+
];
117+
118+
let state={type:'linear',angle:135,stops:[{c:'#667eea',p:0},{c:'#764ba2',p:100}]};
119+
120+
function buildCSS(){
121+
const s=state.stops.map(s=>`${s.c} ${s.p}%`).join(', ');
122+
if(state.type==='linear') return `linear-gradient(${state.angle}deg, ${s})`;
123+
if(state.type==='radial') return `radial-gradient(circle, ${s})`;
124+
return `conic-gradient(from ${state.angle}deg, ${s})`;
125+
}
126+
127+
function render(){
128+
const css=buildCSS();
129+
document.getElementById('preview').style.background=css;
130+
document.getElementById('codeText').textContent=`background: ${css};`;
131+
document.getElementById('angleGroup').style.display=(state.type==='radial')?'none':'block';
132+
renderStops();
133+
}
134+
135+
function renderStops(){
136+
const el=document.getElementById('colorStops');
137+
el.innerHTML='';
138+
state.stops.forEach((s,i)=>{
139+
const row=document.createElement('div');
140+
row.className='color-row';
141+
row.innerHTML=`<input type="color" value="${s.c}" data-i="${i}" class="sc">
142+
<input type="range" min="0" max="100" value="${s.p}" data-i="${i}" class="sp">
143+
<span class="pos">${s.p}%</span>
144+
${state.stops.length>2?`<button data-i="${i}" class="sd">✕</button>`:''}`;
145+
el.appendChild(row);
146+
});
147+
el.querySelectorAll('.sc').forEach(e=>e.oninput=ev=>{state.stops[+ev.target.dataset.i].c=ev.target.value;render()});
148+
el.querySelectorAll('.sp').forEach(e=>e.oninput=ev=>{state.stops[+ev.target.dataset.i].p=+ev.target.value;render()});
149+
el.querySelectorAll('.sd').forEach(e=>e.onclick=ev=>{state.stops.splice(+ev.target.dataset.i,1);render()});
150+
}
151+
152+
function addStop(){
153+
if(state.stops.length>=5)return;
154+
const hue=Math.floor(Math.random()*360);
155+
state.stops.push({c:`hsl(${hue},70%,60%)`,p:50});
156+
// convert hsl to hex via canvas
157+
const ctx=document.createElement('canvas').getContext('2d');
158+
ctx.fillStyle=`hsl(${hue},70%,60%)`;
159+
state.stops[state.stops.length-1].c=ctx.fillStyle;
160+
render();
161+
}
162+
163+
function copyCSS(){
164+
const text=document.getElementById('codeText').textContent;
165+
navigator.clipboard.writeText(text).then(()=>{
166+
const b=document.getElementById('copyBtn');b.textContent='Copied!';b.classList.add('copied');
167+
setTimeout(()=>{b.textContent='Copy';b.classList.remove('copied')},1500);
168+
});
169+
}
170+
171+
// type buttons
172+
document.getElementById('typeBtns').onclick=e=>{
173+
if(!e.target.dataset.type)return;
174+
state.type=e.target.dataset.type;
175+
document.querySelectorAll('.type-btns button').forEach(b=>b.classList.remove('active'));
176+
e.target.classList.add('active');
177+
render();
178+
};
179+
180+
// angle
181+
document.getElementById('angle').oninput=e=>{
182+
state.angle=+e.target.value;
183+
document.getElementById('angleVal').textContent=e.target.value+'°';
184+
render();
185+
};
186+
187+
// presets
188+
const pg=document.getElementById('presetGrid');
189+
PRESETS.forEach((p,i)=>{
190+
const d=document.createElement('div');
191+
d.className='preset-swatch';
192+
const s=p.stops.map(s=>`${s.c} ${s.p}%`).join(', ');
193+
const css=p.type==='linear'?`linear-gradient(${p.angle}deg, ${s})`:p.type==='radial'?`radial-gradient(circle, ${s})`:`conic-gradient(from ${p.angle}deg, ${s})`;
194+
d.style.background=css;
195+
d.onclick=()=>{
196+
state={type:p.type,angle:p.angle,stops:JSON.parse(JSON.stringify(p.stops))};
197+
document.querySelectorAll('.type-btns button').forEach(b=>b.classList.toggle('active',b.dataset.type===state.type));
198+
document.getElementById('angle').value=state.angle;
199+
document.getElementById('angleVal').textContent=state.angle+'°';
200+
render();
201+
};
202+
pg.appendChild(d);
203+
});
204+
205+
render();
206+
</script>
207+
</body>
208+
</html>

0 commit comments

Comments
 (0)