-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
192 lines (166 loc) · 8.69 KB
/
index.html
File metadata and controls
192 lines (166 loc) · 8.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sequence based CSS nth-child Pattern Formula Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<style id="dynamic-style"></style>
</head>
<body class="bg-slate-50 min-h-screen flex flex-col items-center py-12 px-4 sm:px-8">
<div class="max-w-4xl w-full bg-white p-6 sm:p-10 rounded-2xl shadow-xl border border-slate-100">
<div class="mb-8 text-center sm:text-left">
<h1 class="text-3xl font-extrabold text-slate-800 mb-2">CSS <code>:nth-child()</code> Generator</h1>
<p class="text-slate-500 text-lg">Type a sequence of numbers below, and the tool will reverse-engineer the required CSS pattern!</p>
</div>
<!-- Input Section -->
<div class="mb-8">
<label for="sequenceInput" class="block text-sm font-semibold text-slate-700 mb-2">Target Sequence (comma separated)</label>
<div class="relative">
<input
type="text"
id="sequenceInput"
value="1, 4, 5, 8, 9, 12"
placeholder="e.g., 2, 4, 6, 8"
class="w-full text-xl sm:text-2xl px-5 py-4 rounded-xl border-2 border-slate-200 focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition-all font-mono text-slate-700 shadow-inner"
>
</div>
<p class="text-xs text-slate-400 mt-2 ml-1">The algorithm automatically figures out the cyclic jumps and generates the shortest selectors.</p>
</div>
<!-- Code Output Section -->
<div class="bg-slate-900 p-6 rounded-xl font-mono text-sm md:text-base text-slate-300 mb-10 shadow-lg overflow-x-auto border border-slate-800">
<code id="codeOutput" class="leading-relaxed">
<!-- Injected via JS -->
</code>
</div>
<!-- Informational Alert -->
<div class="mb-8 bg-blue-50 border-l-4 border-blue-500 p-4 rounded-r-xl shadow-sm">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-blue-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<p class="text-sm text-blue-700">
<strong>Pro Tip:</strong> Alternatively, if you ever find yourself in a situation where you can't remove other sibling tags like scripts or spans, you can use <code>:nth-of-type(...)</code> instead, which strictly counts only elements of the same tag name!
</p>
</div>
</div>
</div>
<!-- Grid Container -->
<div class="mb-5 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
<h2 class="text-lg font-bold text-slate-800">Live Visualizer Preview</h2>
<div class="flex items-center gap-2 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-full shadow-sm">
<label for="elementCount" class="text-xs font-bold text-blue-700 whitespace-nowrap">Evaluating Elements:</label>
<input type="number" id="elementCount" value="32" min="1" max="500" class="w-16 px-1 py-0.5 text-xs text-center rounded bg-white border border-blue-300 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-all font-mono text-blue-900">
</div>
</div>
<div class="grid grid-cols-4 sm:grid-cols-8 gap-3" id="gridBox">
<!-- Boxes will be Injected via JS -->
</div>
</div>
<script>
const inputEl = document.getElementById('sequenceInput');
const codeOutput = document.getElementById('codeOutput');
const dynamicStyle = document.getElementById('dynamic-style');
const gridBox = document.getElementById('gridBox');
const countInput = document.getElementById('elementCount');
// 1. Generate grid boxes for the live preview dynamically
function renderGrid(count) {
let boxes = '';
for (let i = 1; i <= count; i++) {
boxes += `<div class="grid-item flex items-center justify-center h-14 rounded-lg border-2 border-slate-200 bg-slate-50 text-slate-400 font-bold text-xl transition-all duration-300">${i}</div>`;
}
gridBox.innerHTML = boxes;
}
// Initialize grid
renderGrid(parseInt(countInput.value) || 32);
// Listen for count changes
countInput.addEventListener('input', (e) => {
const newCount = parseInt(e.target.value);
if (newCount > 0 && newCount <= 1000) {
renderGrid(newCount);
}
});
// 2. Algorithm to analyze sequences and create CSS
function analyzeSequence() {
const val = inputEl.value;
// Extract numbers, remove duplicates, and sort them numerically
const nums = [...new Set(val.match(/\d+/g)?.map(Number) || [])].sort((a,b) => a - b);
let rules = [];
if (nums.length === 0) {
updateUI('', '<span class="text-slate-500 italic">/* Enter a sequence above to generate CSS */</span>');
return;
}
if (nums.length === 1) {
// If it's just one number, target that exact child
rules = [nums[0].toString()];
} else {
// Find differences between consecutive elements
let diffs = [];
for (let i = 1; i < nums.length; i++) {
diffs.push(nums[i] - nums[i-1]);
}
// Detect the repeating cycle length in the differences
let cycleLength = 0;
for (let len = 1; len <= diffs.length; len++) {
let isCycle = true;
for (let i = 0; i < diffs.length; i++) {
if (diffs[i] !== diffs[i % len]) {
isCycle = false;
break;
}
}
if (isCycle) {
cycleLength = len;
break;
}
}
// Calculate "a" (the multiplier for 'n')
let a = 0;
for (let i = 0; i < cycleLength; i++) {
a += diffs[i];
}
// Calculate "b" (the offset) for each part of the cycle
for (let i = 0; i < cycleLength; i++) {
let b = nums[i];
if (a === 1) {
rules.push(b === 1 ? 'n' : `n + ${b}`);
} else if (b === a) {
rules.push(`${a}n`); // Simplify an + a to an
} else {
rules.push(`${a}n + ${b}`);
}
}
}
// 3. Render CSS to DOM
const cssSelectors = rules.map(r => `.grid-item:nth-child(${r})`).join(',\n');
const codeDisplay = rules.map(r => `<span class="text-pink-400">.element</span>:<span class="text-purple-400">nth-child</span>(<span class="text-blue-300 font-bold">${r}</span>)`).join(',<br>');
const styleContent = `
${cssSelectors} {
background-color: #3b82f6 !important;
color: white !important;
transform: scale(1.1);
box-shadow: 0 10px 20px -5px rgba(59, 130, 246, 0.4);
border-color: #2563eb !important;
border-style: solid !important;
z-index: 10;
position: relative;
}
`;
const codeText = `${codeDisplay} {<br> <span class="text-slate-400 italic">/* Generated dynamic styles */</span><br>}`;
updateUI(styleContent, codeText);
}
// 4. Update the UI
function updateUI(style, code) {
dynamicStyle.innerHTML = style;
codeOutput.innerHTML = code;
}
// 5. Listen for changes
inputEl.addEventListener('input', analyzeSequence);
// Trigger initial calculation
analyzeSequence();
</script>
</body>
</html>