diff --git a/images/view1.png b/images/view1.png new file mode 100644 index 0000000..3c555a3 Binary files /dev/null and b/images/view1.png differ diff --git a/images/view2.png b/images/view2.png new file mode 100644 index 0000000..29025b1 Binary files /dev/null and b/images/view2.png differ diff --git a/images/view3.png b/images/view3.png new file mode 100644 index 0000000..4e9ea16 Binary files /dev/null and b/images/view3.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..85324e5 --- /dev/null +++ b/index.html @@ -0,0 +1,113 @@ + + + + + + + + Color Number + + + + +
+ + + + +
+ +
+

Color Input

+ + +

Numbers only (0-9). Example: 255000 for orange

+ + +
+ + +
+

Current Color

+ + +
+

Number:

+
000000
+
+ + +
+

Hex:

+
#000000
+
+ + +
+

RGB:

+
rgb(0, 0, 0)
+
+ + +
+

Name:

+
Black
+
+ + +
+

Brightness:

+
+
+
0%
+
+
+ + +
+

Preview:

+
+
+
+ + +
+
+ + + +
+
+ + +
+

Color History

+
+ +
+
+ + + +
+ + + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..95681c1 --- /dev/null +++ b/script.js @@ -0,0 +1,274 @@ +// wait for page to load +document.addEventListener('DOMContentLoaded', () => { + setupApp(); +}); + +// setup everything when page loads +function setupApp() { + const input = document.getElementById('colorInput'); + const reset = document.getElementById('resetBtn'); + const random = document.getElementById('randomBtn'); + const copy = document.getElementById('copyBtn'); + const clearHist = document.getElementById('clearHistoryBtn'); + + // listen to user typing + input?.addEventListener('input', onInputChange); + input?.addEventListener('paste', onPaste); + input?.addEventListener('keydown', onKeyPress); + + // listen to button clicks + reset?.addEventListener('click', resetColor); + random?.addEventListener('click', randomColor); + copy?.addEventListener('click', copyCode); + clearHist?.addEventListener('click', clearHistory); + + // check scroll position + window.addEventListener('scroll', moveInputOnScroll); + + // show saved colors and make hex clickable + loadHistory(); + setupHexClick(); + + // show black color on start + showDefaultColor(); +} + +// check if input is correct (6 numbers) +function validateInput(val) { + if (val === "") return { valid: false, msg: "" }; + if (val.length < 6) return { valid: false, msg: `need ${6 - val.length} more` }; + if (val.length > 6) return { valid: false, msg: "only 6 digits" }; + if (!/^[0-9]{6}$/.test(val)) return { valid: false, msg: "numbers only" }; + return { valid: true, msg: "" }; +} + +// show or hide error message +function showError(error) { + const el = document.getElementById('errorMessage'); + if (!el) return; + if (error) { + el.textContent = error; + el.classList.remove('hidden'); + } else { + el.classList.add('hidden'); + } +} + +// when user types in input +function onInputChange(e) { + const val = e.target.value; + const result = validateInput(val); + const input = e.target; + + if (result.valid) { + input.classList.remove('invalid'); + input.classList.add('valid'); + showError(""); + updateColor(val); + } else { + if (val !== "") { + input.classList.add('invalid'); + input.classList.remove('valid'); + showError(result.msg); + } else { + input.classList.remove('invalid', 'valid'); + showError(""); + } + } +} + +// when user pastes color code +function onPaste(e) { + e.preventDefault(); + const text = (e.clipboardData || window.clipboardData).getData('text'); + if (!/^[0-9]{6}$/.test(text)) return; + e.target.value = text; + onInputChange({ target: e.target }); +} + +// when user presses enter +function onKeyPress(e) { + if (e.key === 'Enter') { + const val = e.target.value; + if (validateInput(val).valid) { + updateColor(val); + } + } +} + +// convert hex to rgb values +function hexToRgb(hex) { + hex = hex.replace('#', ''); + const r = parseInt(hex.substring(0, 2), 16); + const g = parseInt(hex.substring(2, 4), 16); + const b = parseInt(hex.substring(4, 6), 16); + return { r, g, b }; +} + +// change everything when color is updated +function updateColor(colorNum) { + const hex = '#' + colorNum.toUpperCase(); + const { r, g, b } = hexToRgb(hex); + + // update all displays + const colorDisp = document.getElementById('colorDisplay'); + const hexDisp = document.getElementById('hexDisplay'); + const rgbDisp = document.getElementById('rgbDisplay'); + const footer = document.getElementById('currentColor'); + + colorDisp && (colorDisp.textContent = colorNum.toUpperCase()); + hexDisp && (hexDisp.textContent = hex); + rgbDisp && (rgbDisp.textContent = `rgb(${r}, ${g}, ${b})`); + footer && (footer.textContent = `Color: ${hex}`); + + // change page background + document.body.style.backgroundColor = hex; + document.querySelector('.page-container').style.backgroundColor = hex; + + // update bonus features + updateColorName(r, g, b); + updateBrightness(r, g, b); + updateSwatch(hex); + saveColor(hex); +} + +// show color name like red, blue etc +function updateColorName(r, g, b) { + const names = { + '000000': 'Black', 'FFFFFF': 'White', 'FF0000': 'Red', '00FF00': 'Green', + '0000FF': 'Blue', 'FFFF00': 'Yellow', 'FF00FF': 'Magenta', '00FFFF': 'Cyan', + 'FFA500': 'Orange', 'FF69B4': 'Pink', '800080': 'Purple', 'A52A2A': 'Brown' + }; + + const hex = [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('').toUpperCase(); + const name = names[hex] || 'Custom'; + + const el = document.getElementById('colorNameDisplay'); + el && (el.textContent = name); +} + +// show how bright the color is +function updateBrightness(r, g, b) { + const bright = Math.round(((r * 299 + g * 587 + b * 114) / 1000 / 255) * 100); + + const el = document.getElementById('brightnessPercent'); + el && (el.textContent = bright + '%'); + + const bar = document.getElementById('brightnessBar'); + if (bar) { + const pos = (bright / 100) * 100; + bar.style.background = `linear-gradient(to right, #000 0%, #fff 100%), + linear-gradient(to right, #3498db ${pos}%, transparent ${pos}%)`; + } +} + +// show color preview box +function updateSwatch(hex) { + const el = document.getElementById('colorSwatch'); + el && (el.style.backgroundColor = hex); +} + +// save color to history in browser memory +function saveColor(hex) { + let hist = JSON.parse(localStorage.getItem('colorHistory')) || []; + hist = hist.filter(c => c !== hex); + hist.unshift(hex); + if (hist.length > 5) hist.pop(); + localStorage.setItem('colorHistory', JSON.stringify(hist)); + loadHistory(); +} + +// load and show color history +function loadHistory() { + const cont = document.getElementById('colorHistory'); + if (!cont) return; + + const hist = JSON.parse(localStorage.getItem('colorHistory')) || []; + cont.innerHTML = ''; + + // make 5 boxes for colors + for (let i = 0; i < 5; i++) { + const item = document.createElement('div'); + item.className = hist[i] ? 'history-item' : 'history-item empty'; + + if (hist[i]) { + item.style.backgroundColor = hist[i]; + item.textContent = hist[i]; + item.addEventListener('click', () => { + const inp = document.getElementById('colorInput'); + inp.value = hist[i].replace('#', ''); + onInputChange({ target: inp }); + }); + } else { + item.textContent = '-'; + } + + cont.appendChild(item); + } + + // show clear button only if there are saved colors + const clearBtn = document.getElementById('clearHistoryBtn'); + clearBtn && (clearBtn.style.display = hist.length > 0 ? 'block' : 'none'); +} + +// delete all saved colors +function clearHistory() { + if (confirm('Clear history?')) { + localStorage.removeItem('colorHistory'); + loadHistory(); + } +} + +// make hex code clickable to copy +function setupHexClick() { + const hex = document.getElementById('hexDisplay'); + hex && (hex.addEventListener('click', copyCode), hex.style.cursor = 'pointer'); +} + +// copy hex code to clipboard +function copyCode() { + const hex = document.getElementById('hexDisplay')?.textContent; + if (!hex) return; + + navigator.clipboard.writeText(hex).then(() => { + const btn = document.getElementById('copyBtn'); + const orig = btn.textContent; + btn.textContent = 'Copied!'; + setTimeout(() => (btn.textContent = orig), 1500); + }).catch(() => alert('Copy failed')); +} + +// reset to black +function resetColor() { + const inp = document.getElementById('colorInput'); + inp.value = ''; + inp.classList.remove('valid', 'invalid'); + showError(''); + updateColor('000000'); +} + +// pick random color +function randomColor() { + const rand = Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0'); + const inp = document.getElementById('colorInput'); + inp.value = rand; + updateColor(rand); +} + +// move input box to corner when scrolling +function moveInputOnScroll() { + const section = document.querySelector('.input-section'); + if (!section) return; + + const rect = section.getBoundingClientRect(); + if (rect.top < 50) { + section.classList.add('scrolled'); + } else { + section.classList.remove('scrolled'); + } +} + +// show black color at start +function showDefaultColor() { + updateColor('000000'); +} diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..c4fd354 --- /dev/null +++ b/styles.css @@ -0,0 +1,465 @@ +/* reset everything */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* colors and sizes */ +:root { + --primary: #3498db; + --secondary: #2ecc71; + --danger: #e74c3c; + --dark: #333; + --light: #fff; + --gray: #bdc3c7; + --spacing: 1rem; + --radius: 8px; +} + +/* page settings */ +html { + scroll-behavior: smooth; + font-size: 16px; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + line-height: 1.6; + color: var(--dark); + background-color: #ecf0f1; + min-height: 100vh; + transition: background-color 0.5s ease; +} + +/* main layout */ +.page-container { + width: 100%; + min-height: 100vh; + display: grid; + grid-template-rows: auto 1fr auto; + background-color: #ecf0f1; + transition: background-color 0.5s ease; +} + +/* top header */ +.page-header { + text-align: center; + padding: 2rem 1rem; + background: linear-gradient(135deg, var(--primary), var(--secondary)); + color: var(--light); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.page-header h1 { + font-size: 2.5rem; + margin-bottom: 0.5rem; +} + +.subtitle { + font-size: 1rem; + font-weight: 300; + opacity: 0.9; +} + +/* center content */ +.content-wrapper { + max-width: 600px; + margin: 0 auto; + padding: 2rem 1rem; + width: 100%; +} + +/* card styling */ +section { + margin-bottom: 1.5rem; + background: var(--light); + padding: 1.5rem; + border-radius: var(--radius); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + animation: slideIn 0.6s ease-out backwards; +} + +/* animation for sections */ +section:nth-child(2) { animation-delay: 0s; } +section:nth-child(3) { animation-delay: 0.1s; } +section:nth-child(4) { animation-delay: 0.2s; } +section:nth-child(5) { animation-delay: 0.3s; } + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* titles in sections */ +.section-title { + font-size: 1.3rem; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 2px solid var(--primary); +} + +/* input field styling */ +.input-label { + display: block; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.color-input { + width: 100%; + padding: 1rem; + font-size: 1.2rem; + border: 2px solid var(--gray); + border-radius: var(--radius); + font-family: 'Courier New', monospace; + letter-spacing: 2px; + text-align: center; + transition: all 0.3s ease; + cursor: text; +} + +.color-input:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1); +} + +.color-input:hover:not(:focus) { + border-color: #95a5a6; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +/* good input */ +.color-input.valid { + border-color: var(--secondary); + box-shadow: 0 0 0 3px rgba(46, 204, 113, 0.15); +} + +/* bad input */ +.color-input.invalid { + border-color: var(--danger); + animation: shake 0.3s ease; +} + +@keyframes shake { + 0%, 100% { transform: translateX(0); } + 25% { transform: translateX(-5px); } + 75% { transform: translateX(5px); } +} + +.input-hint { + font-size: 0.9rem; + color: #7f8c8d; + margin-top: 0.5rem; + font-style: italic; +} + +/* error message */ +.error-message { + color: var(--danger); + font-size: 0.9rem; + font-weight: 500; + margin-top: 1rem; + padding: 1rem; + background-color: rgba(231, 76, 60, 0.1); + border-left: 3px solid var(--danger); + border-radius: 3px; + display: block; + transition: opacity 0.2s ease; +} + +.error-message.hidden { + display: none; +} + +/* display boxes */ +.display-area, .hex-area, .rgb-area, +.color-name-area, .brightness-area, .preview-area { + padding: 1.5rem; + background-color: rgba(52, 152, 219, 0.05); + border-radius: var(--radius); + border: 1px solid rgba(52, 152, 219, 0.2); + margin-bottom: 1.5rem; +} + +.display-area:last-child, .hex-area:last-child, .rgb-area:last-child, +.color-name-area:last-child, .brightness-area:last-child, .preview-area:last-child { + margin-bottom: 0; +} + +/* text labels */ +.display-label { + font-size: 0.85rem; + font-weight: 700; + color: #7f8c8d; + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: 0.5rem; +} + +/* color displays */ +.color-display, .hex-display, .rgb-display, .color-name-display { + font-family: 'Courier New', monospace; + font-weight: bold; + color: var(--primary); + text-align: center; + transition: all 0.4s ease; + word-break: break-all; +} + +.color-display { + font-size: 3rem; + min-height: 5rem; + display: flex; + align-items: center; + justify-content: center; +} + +.hex-display, .rgb-display, .color-name-display { + font-size: 1.1rem; +} + +/* clickable hex */ +.hex-display { + cursor: pointer; + padding: 0.5rem; + border-radius: 4px; + transition: all 0.2s ease; +} + +.hex-display:hover { + background-color: rgba(52, 152, 219, 0.1); + transform: scale(1.05); +} + +/* brightness bar */ +.brightness-container { + display: flex; + gap: 1rem; + align-items: center; +} + +.brightness-bar { + flex: 1; + height: 20px; + background: linear-gradient(to right, #000, #fff); + border-radius: 4px; + border: 1px solid var(--gray); + position: relative; +} + +.brightness-percent { + min-width: 50px; + text-align: right; + font-weight: 600; + color: var(--primary); +} + +/* color preview box */ +.color-swatch { + width: 100%; + height: 100px; + border-radius: var(--radius); + border: 2px solid var(--gray); + background-color: #000; + transition: background-color 0.4s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +/* buttons layout */ +.button-section { + margin-top: 2rem; +} + +.button-group { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; +} + +/* button styling */ +.btn { + padding: 1rem; + font-size: 1rem; + font-weight: 600; + border: none; + border-radius: var(--radius); + cursor: pointer; + transition: all 0.3s ease; + text-transform: uppercase; + letter-spacing: 1px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + width: 100%; +} + +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15); +} + +.btn:active { + transform: translateY(0); +} + +/* button colors */ +.reset-btn { + background-color: var(--danger); + color: var(--light); +} + +.reset-btn:hover { background-color: #c0392b; } + +.random-btn { + background-color: var(--secondary); + color: var(--light); +} + +.random-btn:hover { background-color: #27ae60; } + +.copy-btn { + background-color: var(--primary); + color: var(--light); +} + +.copy-btn:hover { background-color: #2980b9; } + +/* history grid */ +.color-history { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 1rem; +} + +/* history item styling */ +.history-item { + width: 100%; + aspect-ratio: 1; + border-radius: var(--radius); + border: 2px solid var(--gray); + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: 600; + color: var(--light); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.history-item:hover { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +/* empty slots */ +.history-item.empty { + background-color: #ecf0f1; + color: #7f8c8d; + cursor: not-allowed; +} + +/* clear button */ +.clear-history-btn { + background-color: #95a5a6; + color: var(--light); + margin-top: 1rem; +} + +.clear-history-btn:hover { background-color: #7f8c8d; } + +/* footer */ +.page-footer { + text-align: center; + padding: 1.5rem 2rem; + background-color: rgba(0, 0, 0, 0.05); + border-top: 1px solid var(--gray); + font-size: 0.9rem; + color: var(--dark); +} + +.footer-text { + margin-bottom: 0.5rem; +} + +.footer-credits { + font-size: 0.85rem; + color: #7f8c8d; +} + +.footer-credits a { + color: var(--primary); + text-decoration: none; + transition: color 0.3s ease; +} + +.footer-credits a:hover { + text-decoration: underline; +} + +/* hidden class */ +.hidden { display: none; } + +/* input fixed to corner on scroll */ +.input-section.scrolled { + position: fixed; + top: 20px; + left: 20px; + width: 280px; + max-width: 40%; + transform: scale(0.85); + z-index: 1000; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); +} + +.input-section.scrolled .input-label, +.input-section.scrolled .input-hint, +.input-section.scrolled .section-title, +.input-section.scrolled .error-message { + display: none; +} + +.input-section.scrolled .color-input { + font-size: 0.95rem; + padding: 0.75rem; +} + +/* mobile phones */ +@media (max-width: 480px) { + .page-header h1 { font-size: 1.8rem; } + .color-display { font-size: 2.5rem; min-height: 4rem; } + .color-history { grid-template-columns: repeat(4, 1fr); } + .color-swatch { height: 80px; } +} + +/* tablets */ +@media (min-width: 481px) and (max-width: 768px) { + .page-header h1 { font-size: 2.2rem; } + .button-group { grid-template-columns: repeat(2, 1fr); } + .random-btn { grid-column: 1; } + .copy-btn { grid-column: 2; } + .reset-btn { grid-column: 1 / -1; } +} + +/* big screens */ +@media (min-width: 769px) { + .page-header h1 { font-size: 2.8rem; } + .button-group { grid-template-columns: repeat(3, 1fr); } + .color-display { font-size: 4rem; min-height: 6rem; } +} + +/* if user prefers reduced animations */ +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +}