|
| 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