UI Component
✨ NewLayout

Animated Wave Mega Footer with Newsletter

A complete website footer topped with layered animated SVG waves, a newsletter call-to-action with validation and loading state, four link columns, brand-coloured social icons, a live status indicator and back-to-top button. On mobile the link columns turn into an accordion. Pure HTML, CSS and vanilla JavaScript.

September 26, 20263 views
  • Footer
  • footer
  • svg-waves
  • newsletter
  • responsive
  • accordion
  • website-layout
Animated Wave Mega Footer with Newsletter
Free

Download instantly, no signup required.

Features Included

Three layered SVG waves moving at different speeds (seamless loop)
Newsletter CTA with email validation, shake on error and loading spinner
Brand block with logo, description and 5 social icons that light up in brand colours
Four link columns with animated underlines and 'New' / 'Hiring' pills
Status indicator, auto-updating copyright year and back-to-top button
Link columns collapse into an accordion on mobile
Dependencies
Google Fonts — Poppinscdn

Animated Wave Mega Footer with Newsletter

A footer that finishes your site in style — flowing SVG waves, newsletter signup, mega link columns and a mobile accordion. HTML, CSS and vanilla JavaScript.


What's Included

  • Three layered SVG waves moving at different speeds (seamless loop)
  • Newsletter CTA with email validation, shake on error and loading spinner
  • Brand block with logo, description and 5 social icons that light up in brand colours
  • Four link columns with animated underlines and 'New' / 'Hiring' pills
  • Status indicator, auto-updating copyright year and back-to-top button
  • Link columns collapse into an accordion on mobile

Dependencies

Already linked inside the component's files — no extra setup needed.


Desktop Preview


HTML

html
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>Wave Mega Footer | MetaSkillGroup</title>
7    <link rel="stylesheet" href="style.css" />
8  </head>
9  <body>
10    <!-- created by metaskillgroup-team -->
11    <main class="page-demo">
12      <p>Scroll down to see the footer ↓</p>
13    </main>
14
15    <footer class="footer">
16      <!-- Animated layered waves -->
17      <div class="waves" aria-hidden="true">
18        <svg viewBox="0 0 1440 120" preserveAspectRatio="none">
19          <defs>
20            <path id="wave" d="M0 60 Q 360 110 720 60 T 1440 60 T 2160 60 T 2880 60 V120 H0Z" />
21          </defs>
22          <g class="wave-layer w1"><use href="#wave" /></g>
23          <g class="wave-layer w2"><use href="#wave" /></g>
24          <g class="wave-layer w3"><use href="#wave" /></g>
25        </svg>
26      </div>
27
28      <div class="footer-body">
29        <!-- CTA band -->
30        <section class="cta">
31          <div>
32            <h2>Ready to build something great?</h2>
33            <p>Join 40,000+ developers getting one practical tip every week.</p>
34          </div>
35          <form class="newsletter" novalidate>
36            <div class="nl-field">
37              <svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><path d="M4 6h16v12H4z M4 7l8 6 8-6" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
38              <input type="email" placeholder="you@example.com" aria-label="Email address" required />
39              <button type="submit">
40                <span class="nl-text">Subscribe</span>
41                <span class="nl-spinner" aria-hidden="true"></span>
42              </button>
43            </div>
44            <p class="nl-msg" role="status"></p>
45          </form>
46        </section>
47
48        <!-- Link columns -->
49        <div class="columns">
50          <div class="brand">
51            <a href="#" class="logo">
52              <span class="logo-mark">M</span>
53              MetaSkill
54            </a>
55            <p>Free, production-ready UI components and templates for modern web projects.</p>
56            <ul class="socials">
57              <li><a href="#" aria-label="GitHub" style="--brand: #f0f6fc"><svg viewBox="0 0 24 24"><path d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.7c-2.78.6-3.37-1.34-3.37-1.34-.45-1.16-1.1-1.46-1.1-1.46-.9-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.9 1.52 2.34 1.08 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.1.39-1.99 1.03-2.69-.1-.25-.45-1.27.1-2.64 0 0 .84-.27 2.75 1.02a9.6 9.6 0 0 1 5 0c1.91-1.29 2.75-1.02 2.75-1.02.55 1.37.2 2.39.1 2.64.64.7 1.03 1.6 1.03 2.69 0 3.84-2.34 4.69-4.57 4.93.36.31.68.92.68 1.85v2.75c0 .27.18.58.69.48A10 10 0 0 0 12 2z" fill="currentColor"/></svg></a></li>
58              <li><a href="#" aria-label="X / Twitter" style="--brand: #e7e9ea"><svg viewBox="0 0 24 24"><path d="M17.8 3h3.1l-6.8 7.8L22 21h-6.3l-4.9-6.4L5.2 21H2.1l7.3-8.3L1.8 3h6.4l4.4 5.8L17.8 3zm-1.1 16.2h1.7L7.4 4.7H5.6l11.1 14.5z" fill="currentColor"/></svg></a></li>
59              <li><a href="#" aria-label="LinkedIn" style="--brand: #0a66c2"><svg viewBox="0 0 24 24"><path d="M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5zM3 9h4v12H3zM9 9h3.8v1.7h.05c.53-1 1.83-2.05 3.77-2.05 4.03 0 4.78 2.65 4.78 6.1V21h-4v-5.6c0-1.34-.03-3.06-1.86-3.06-1.87 0-2.15 1.46-2.15 2.96V21H9z" fill="currentColor"/></svg></a></li>
60              <li><a href="#" aria-label="YouTube" style="--brand: #ff0033"><svg viewBox="0 0 24 24"><path d="M23 7.2a3 3 0 0 0-2.1-2.1C19 4.6 12 4.6 12 4.6s-7 0-8.9.5A3 3 0 0 0 1 7.2 31 31 0 0 0 .5 12a31 31 0 0 0 .5 4.8 3 3 0 0 0 2.1 2.1c1.9.5 8.9.5 8.9.5s7 0 8.9-.5a3 3 0 0 0 2.1-2.1 31 31 0 0 0 .5-4.8 31 31 0 0 0-.5-4.8zM9.75 15.02V8.98L15.5 12l-5.75 3.02z" fill="currentColor"/></svg></a></li>
61              <li><a href="#" aria-label="Instagram" style="--brand: #e1306c"><svg viewBox="0 0 24 24"><path d="M12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10zm0 8.2a3.2 3.2 0 1 1 0-6.4 3.2 3.2 0 0 1 0 6.4zM17.3 5.5a1.2 1.2 0 1 0 0 2.4 1.2 1.2 0 0 0 0-2.4zM12 2c-2.7 0-3 0-4.1.06C4.2 2.2 2.2 4.2 2.06 7.9 2 9 2 9.3 2 12s0 3 .06 4.1c.14 3.7 2.14 5.7 5.84 5.84C9 22 9.3 22 12 22s3 0 4.1-.06c3.7-.14 5.7-2.14 5.84-5.84C22 15 22 14.7 22 12s0-3-.06-4.1C21.8 4.2 19.8 2.2 16.1 2.06 15 2 14.7 2 12 2zm0 1.8c2.67 0 2.99 0 4.04.06 2.7.12 3.97 1.4 4.1 4.1.05 1.05.06 1.37.06 4.04s0 2.99-.06 4.04c-.13 2.7-1.4 3.97-4.1 4.1-1.05.05-1.37.06-4.04.06s-2.99 0-4.04-.06c-2.71-.13-3.97-1.41-4.1-4.1C3.81 14.99 3.8 14.67 3.8 12s0-2.99.06-4.04c.13-2.7 1.4-3.97 4.1-4.1C9.01 3.81 9.33 3.8 12 3.8z" fill="currentColor"/></svg></a></li>
62            </ul>
63          </div>
64
65          <nav class="col" aria-label="Product">
66            <h3>Product<span class="col-toggle" aria-hidden="true"></span></h3>
67            <ul>
68              <li><a href="#">Components</a></li>
69              <li><a href="#">Templates</a></li>
70              <li><a href="#">Projects <span class="pill">New</span></a></li>
71              <li><a href="#">Changelog</a></li>
72              <li><a href="#">Roadmap</a></li>
73            </ul>
74          </nav>
75
76          <nav class="col" aria-label="Resources">
77            <h3>Resources<span class="col-toggle" aria-hidden="true"></span></h3>
78            <ul>
79              <li><a href="#">Documentation</a></li>
80              <li><a href="#">Blog</a></li>
81              <li><a href="#">Tutorials</a></li>
82              <li><a href="#">Community</a></li>
83              <li><a href="#">Help center</a></li>
84            </ul>
85          </nav>
86
87          <nav class="col" aria-label="Company">
88            <h3>Company<span class="col-toggle" aria-hidden="true"></span></h3>
89            <ul>
90              <li><a href="#">About us</a></li>
91              <li><a href="#">Careers <span class="pill pill-hiring">Hiring</span></a></li>
92              <li><a href="#">Mentorship</a></li>
93              <li><a href="#">Contact</a></li>
94              <li><a href="#">Press kit</a></li>
95            </ul>
96          </nav>
97
98          <nav class="col" aria-label="Legal">
99            <h3>Legal<span class="col-toggle" aria-hidden="true"></span></h3>
100            <ul>
101              <li><a href="#">Privacy policy</a></li>
102              <li><a href="#">Terms of service</a></li>
103              <li><a href="#">Cookie policy</a></li>
104              <li><a href="#">Licenses</a></li>
105            </ul>
106          </nav>
107        </div>
108
109        <!-- Bottom bar -->
110        <div class="bottom">
111          <p>© <span class="year"></span> MetaSkillGroup. All rights reserved.</p>
112          <div class="status">
113            <span class="status-dot"></span>
114            All systems operational
115          </div>
116          <button class="to-top" aria-label="Back to top">
117            <svg viewBox="0 0 24 24" width="20" height="20"><path d="M12 19V5M5 12l7-7 7 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
118          </button>
119        </div>
120      </div>
121    </footer>
122
123    <script src="script.js"></script>
124  </body>
125</html>
126

CSS

css
1/* Importing Google Fonts - Poppins */
2@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap");
3
4* {
5  margin: 0;
6  padding: 0;
7  box-sizing: border-box;
8  font-family: "Poppins", sans-serif;
9}
10
11:root {
12  --page: #eef4ff;
13  --footer: #0b1437;
14  --footer-2: #111c4a;
15  --text: #e6ebff;
16  --muted: #98a3cc;
17  --border: rgba(255, 255, 255, 0.09);
18  --accent: #38bdf8;
19  --accent-2: #818cf8;
20  --ok: #22c55e;
21  --error: #fb7185;
22}
23
24body {
25  background: var(--page);
26}
27
28a {
29  color: inherit;
30  text-decoration: none;
31}
32
33button {
34  font: inherit;
35  color: inherit;
36  border: none;
37  background: none;
38  cursor: pointer;
39}
40
41.page-demo {
42  min-height: 70vh;
43  display: grid;
44  place-items: center;
45  color: #5b6b96;
46  font-weight: 500;
47}
48
49/* ---------- Waves ---------- */
50.footer {
51  position: relative;
52  color: var(--text);
53}
54
55.waves {
56  height: 120px;
57  margin-bottom: -2px;
58  overflow: hidden;
59}
60
61.waves svg {
62  width: 100%;
63  height: 100%;
64  display: block;
65}
66
67.wave-layer {
68  animation: wave linear infinite;
69}
70
71.w1 {
72  fill: rgba(56, 189, 248, 0.25);
73  animation-duration: 18s;
74}
75
76.w2 {
77  fill: rgba(129, 140, 248, 0.35);
78  animation-duration: 12s;
79  transform: translateY(12px);
80}
81
82.w3 {
83  fill: var(--footer);
84  animation-duration: 8s;
85  transform: translateY(24px);
86}
87
88@keyframes wave {
89  from {
90    translate: 0 0;
91  }
92  to {
93    translate: -1440px 0;
94  }
95}
96
97.w2 {
98  animation-name: wave-rev;
99}
100
101@keyframes wave-rev {
102  from {
103    translate: -1440px 0;
104  }
105  to {
106    translate: 0 0;
107  }
108}
109
110.footer-body {
111  background: var(--footer);
112  padding: 20px 24px 28px;
113}
114
115.footer-body > * {
116  max-width: 1200px;
117  margin-left: auto;
118  margin-right: auto;
119}
120
121/* ---------- CTA band ---------- */
122.cta {
123  display: flex;
124  justify-content: space-between;
125  align-items: center;
126  gap: 32px;
127  flex-wrap: wrap;
128  padding: 32px;
129  border-radius: 24px;
130  background:
131    radial-gradient(circle at 0% 0%, rgba(56, 189, 248, 0.25), transparent 50%),
132    radial-gradient(circle at 100% 100%, rgba(129, 140, 248, 0.3), transparent 50%),
133    var(--footer-2);
134  border: 1px solid var(--border);
135}
136
137.cta h2 {
138  font-size: clamp(1.3rem, 3vw, 1.75rem);
139  font-weight: 700;
140  letter-spacing: -0.02em;
141}
142
143.cta p {
144  margin-top: 6px;
145  color: var(--muted);
146  font-size: 0.95rem;
147}
148
149.newsletter {
150  flex: 1;
151  max-width: 460px;
152  min-width: 260px;
153}
154
155.nl-field {
156  display: flex;
157  align-items: center;
158  gap: 10px;
159  padding: 6px 6px 6px 16px;
160  border-radius: 14px;
161  background: rgba(255, 255, 255, 0.06);
162  border: 1.5px solid var(--border);
163  color: var(--muted);
164  transition:
165    border-color 0.2s ease,
166    box-shadow 0.2s ease;
167}
168
169.nl-field:focus-within {
170  border-color: var(--accent);
171  box-shadow: 0 0 0 4px rgba(56, 189, 248, 0.15);
172}
173
174.newsletter.invalid .nl-field {
175  border-color: var(--error);
176  animation: shake 0.35s;
177}
178
179@keyframes shake {
180  25% {
181    transform: translateX(-5px);
182  }
183  75% {
184    transform: translateX(5px);
185  }
186}
187
188.nl-field input {
189  flex: 1;
190  min-width: 0;
191  padding: 10px 0;
192  background: none;
193  border: none;
194  outline: none;
195  color: var(--text);
196  font-size: 0.95rem;
197}
198
199.nl-field input::placeholder {
200  color: #6b77a3;
201}
202
203.nl-field button {
204  position: relative;
205  padding: 11px 20px;
206  border-radius: 10px;
207  font-weight: 600;
208  font-size: 0.92rem;
209  color: #0b1437;
210  background: linear-gradient(90deg, var(--accent), var(--accent-2));
211  transition:
212    transform 0.2s ease,
213    box-shadow 0.2s ease;
214}
215
216.nl-field button:hover {
217  transform: translateY(-1px);
218  box-shadow: 0 8px 20px rgba(56, 189, 248, 0.35);
219}
220
221.nl-spinner {
222  position: absolute;
223  inset: 0;
224  width: 18px;
225  height: 18px;
226  margin: auto;
227  border-radius: 50%;
228  border: 2.5px solid rgba(11, 20, 55, 0.3);
229  border-top-color: #0b1437;
230  animation: spin 0.7s linear infinite;
231  display: none;
232}
233
234.newsletter.loading .nl-text {
235  visibility: hidden;
236}
237
238.newsletter.loading .nl-spinner {
239  display: block;
240}
241
242@keyframes spin {
243  to {
244    transform: rotate(360deg);
245  }
246}
247
248.nl-msg {
249  min-height: 1.3em;
250  margin-top: 8px;
251  padding-left: 4px;
252  font-size: 0.82rem;
253}
254
255.nl-msg.ok {
256  color: var(--ok);
257}
258
259.nl-msg.bad {
260  color: var(--error);
261}
262
263/* ---------- Columns ---------- */
264.columns {
265  display: grid;
266  grid-template-columns: 1.6fr repeat(4, 1fr);
267  gap: 32px;
268  padding: 56px 0 44px;
269}
270
271.logo {
272  display: inline-flex;
273  align-items: center;
274  gap: 10px;
275  font-size: 1.25rem;
276  font-weight: 700;
277}
278
279.logo-mark {
280  display: grid;
281  place-items: center;
282  width: 36px;
283  height: 36px;
284  border-radius: 10px;
285  color: #0b1437;
286  background: linear-gradient(135deg, var(--accent), var(--accent-2));
287}
288
289.brand p {
290  max-width: 290px;
291  margin: 16px 0 22px;
292  color: var(--muted);
293  font-size: 0.9rem;
294  line-height: 1.7;
295}
296
297.socials {
298  display: flex;
299  gap: 10px;
300  list-style: none;
301}
302
303.socials a {
304  display: grid;
305  place-items: center;
306  width: 40px;
307  height: 40px;
308  border-radius: 12px;
309  color: var(--muted);
310  background: rgba(255, 255, 255, 0.05);
311  border: 1px solid var(--border);
312  transition:
313    color 0.25s ease,
314    background 0.25s ease,
315    transform 0.25s ease,
316    border-color 0.25s ease;
317}
318
319.socials svg {
320  width: 18px;
321  height: 18px;
322}
323
324.socials a:hover {
325  color: #fff;
326  background: var(--brand);
327  border-color: var(--brand);
328  transform: translateY(-4px);
329}
330
331/* Light brand colours need dark icons */
332.socials a[aria-label="GitHub"]:hover,
333.socials a[aria-label="X / Twitter"]:hover {
334  color: #0b1437;
335}
336
337.col h3 {
338  display: flex;
339  justify-content: space-between;
340  align-items: center;
341  margin-bottom: 16px;
342  font-size: 0.95rem;
343  font-weight: 600;
344}
345
346.col ul {
347  list-style: none;
348  display: flex;
349  flex-direction: column;
350  gap: 12px;
351}
352
353.col a {
354  position: relative;
355  display: inline-flex;
356  align-items: center;
357  gap: 8px;
358  font-size: 0.9rem;
359  color: var(--muted);
360  transition:
361    color 0.2s ease,
362    transform 0.2s ease;
363}
364
365/* Underline that grows from the left */
366.col a::after {
367  content: "";
368  position: absolute;
369  left: 0;
370  bottom: -3px;
371  width: 100%;
372  height: 1.5px;
373  background: var(--accent);
374  transform: scaleX(0);
375  transform-origin: left;
376  transition: transform 0.3s ease;
377}
378
379.col a:hover {
380  color: var(--text);
381  transform: translateX(3px);
382}
383
384.col a:hover::after {
385  transform: scaleX(1);
386}
387
388.pill {
389  padding: 1px 8px;
390  border-radius: 99px;
391  font-size: 0.68rem;
392  font-weight: 600;
393  color: var(--accent);
394  background: rgba(56, 189, 248, 0.14);
395}
396
397.pill-hiring {
398  color: var(--ok);
399  background: rgba(34, 197, 94, 0.14);
400}
401
402.col-toggle {
403  display: none;
404}
405
406/* ---------- Bottom bar ---------- */
407.bottom {
408  display: flex;
409  justify-content: space-between;
410  align-items: center;
411  gap: 16px;
412  flex-wrap: wrap;
413  padding-top: 24px;
414  border-top: 1px solid var(--border);
415  font-size: 0.85rem;
416  color: var(--muted);
417}
418
419.status {
420  display: flex;
421  align-items: center;
422  gap: 8px;
423}
424
425.status-dot {
426  position: relative;
427  width: 8px;
428  height: 8px;
429  border-radius: 50%;
430  background: var(--ok);
431}
432
433.status-dot::after {
434  content: "";
435  position: absolute;
436  inset: 0;
437  border-radius: 50%;
438  background: var(--ok);
439  animation: ping 1.8s ease-out infinite;
440}
441
442@keyframes ping {
443  to {
444    transform: scale(3);
445    opacity: 0;
446  }
447}
448
449.to-top {
450  display: grid;
451  place-items: center;
452  width: 44px;
453  height: 44px;
454  border-radius: 50%;
455  background: rgba(255, 255, 255, 0.06);
456  border: 1px solid var(--border);
457  transition:
458    background 0.2s ease,
459    transform 0.2s ease;
460}
461
462.to-top:hover {
463  background: var(--accent);
464  color: #0b1437;
465  transform: translateY(-4px);
466}
467
468/* ---------- Responsive ---------- */
469@media (max-width: 1000px) {
470  .columns {
471    grid-template-columns: repeat(4, 1fr);
472  }
473
474  .brand {
475    grid-column: 1 / -1;
476  }
477}
478
479/* On phones the link columns become an accordion */
480@media (max-width: 640px) {
481  .waves {
482    height: 70px;
483  }
484
485  .cta {
486    padding: 24px;
487  }
488
489  .columns {
490    grid-template-columns: 1fr;
491    gap: 0;
492    padding-top: 40px;
493  }
494
495  .brand {
496    margin-bottom: 24px;
497  }
498
499  .col {
500    border-bottom: 1px solid var(--border);
501  }
502
503  .col h3 {
504    margin: 0;
505    padding: 16px 0;
506    cursor: pointer;
507  }
508
509  .col-toggle {
510    display: block;
511    position: relative;
512    width: 14px;
513    height: 14px;
514  }
515
516  .col-toggle::before,
517  .col-toggle::after {
518    content: "";
519    position: absolute;
520    top: 6px;
521    left: 0;
522    width: 14px;
523    height: 2px;
524    border-radius: 2px;
525    background: var(--muted);
526    transition: transform 0.3s ease;
527  }
528
529  .col-toggle::after {
530    transform: rotate(90deg);
531  }
532
533  .col.open .col-toggle::after {
534    transform: rotate(0);
535  }
536
537  .col ul {
538    max-height: 0;
539    overflow: hidden;
540    transition:
541      max-height 0.4s ease,
542      padding 0.4s ease;
543  }
544
545  .col.open ul {
546    max-height: 300px;
547    padding-bottom: 18px;
548  }
549
550  .bottom {
551    flex-direction: column-reverse;
552    text-align: center;
553  }
554}
555
556@media (prefers-reduced-motion: reduce) {
557  *,
558  *::before,
559  *::after {
560    animation: none !important;
561    transition-duration: 0.01ms !important;
562  }
563}
564

JavaScript

javascript
1// Current year in the copyright line
2document.querySelector(".year").textContent = new Date().getFullYear();
3
4// Newsletter form with validation + fake request
5const form = document.querySelector(".newsletter");
6const input = form.querySelector("input");
7const msg = form.querySelector(".nl-msg");
8
9const showMessage = (text, type) => {
10  msg.textContent = text;
11  msg.className = `nl-msg ${type}`;
12};
13
14form.addEventListener("submit", (e) => {
15  e.preventDefault();
16  const email = input.value.trim();
17  const valid = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email);
18
19  form.classList.remove("invalid");
20  if (!valid) {
21    // Re-trigger the shake animation
22    void form.offsetWidth;
23    form.classList.add("invalid");
24    showMessage(email ? "That email doesn't look right." : "Please enter your email.", "bad");
25    input.focus();
26    return;
27  }
28
29  form.classList.add("loading");
30  showMessage("", "");
31  setTimeout(() => {
32    form.classList.remove("loading");
33    showMessage(`🎉 You're in! Check ${email} to confirm.`, "ok");
34    input.value = "";
35  }, 1200);
36});
37
38input.addEventListener("input", () => {
39  if (form.classList.contains("invalid")) {
40    form.classList.remove("invalid");
41    showMessage("", "");
42  }
43});
44
45// Back to top
46document.querySelector(".to-top").addEventListener("click", () => {
47  window.scrollTo({ top: 0, behavior: "smooth" });
48});
49
50// Mobile accordion for the link columns
51const mobile = window.matchMedia("(max-width: 640px)");
52
53document.querySelectorAll(".col h3").forEach((heading) => {
54  heading.addEventListener("click", () => {
55    if (!mobile.matches) return;
56    const col = heading.parentElement;
57    const open = col.classList.toggle("open");
58    heading.setAttribute("aria-expanded", String(open));
59  });
60});
61

Built by Meta Skill Group — copy it, use it, make it yours.

Built With

🌐

HTML5

🎨

CSS3

⚡

JavaScript

Compatibility

Browsers
ChromeOperaBraveFirefoxSafariArcVivaldiEdge
Devices
DesktopSmartwatchTVTabletMobile
Frameworks
Vanilla JSHTML/CSS

Found this useful?

MetaSkillGroup

Written by

MetaSkillGroup

September 26, 2026

❓ FAQs

Subscribe to Newsletter

Get latest updates, tutorials and resources delivered to your inbox.

No spam. Unsubscribe anytime.

Animated Wave Footer with Newsletter | HTML CSS JS | MetaSkillGroup