fix: match mobile footer design
This commit is contained in:
@@ -1,30 +1,46 @@
|
|||||||
/* Footer styles */
|
/* Footer styles */
|
||||||
|
|
||||||
.site-footer {
|
.site-footer {
|
||||||
border-bottom: 1rem solid var(--color-orange, #F26B53);
|
border-bottom: 1rem solid var(--color-orange, #f26b53);
|
||||||
|
|
||||||
a { @apply text-white transition-colors duration-300 hover:text-secondary-400 focus-visible:text-secondary-400; }
|
a {
|
||||||
|
@apply text-white transition-colors duration-300 hover:text-secondary-400 focus-visible:text-secondary-400;
|
||||||
.widget {
|
|
||||||
li { @apply text-16px my-1 mb-2 leading-4; }
|
|
||||||
|
|
||||||
h4 { @apply font-bold text-18px text-secondary mb-2; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-footer-menu-container { @apply grow; }
|
.widget {
|
||||||
|
li {
|
||||||
|
@apply text-16px my-1 mb-2 leading-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
@apply font-bold text-18px text-secondary mb-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-footer-menu-container {
|
||||||
|
@apply grow;
|
||||||
|
}
|
||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
p { @apply text-white leading-none m-0 p-0; }
|
p {
|
||||||
|
@apply text-white leading-none m-0 p-0;
|
||||||
|
}
|
||||||
|
|
||||||
a { @apply text-white hover:text-primary-500 underline underline-offset-2; }
|
a {
|
||||||
|
@apply text-white hover:text-primary-500 underline underline-offset-2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact__item {
|
.contact__item {
|
||||||
@apply flex justify-start items-start font-light text-white text-14px mb-2;
|
@apply flex justify-start items-start font-light text-white text-14px mb-2;
|
||||||
|
|
||||||
p { @apply m-0 p-0; }
|
p {
|
||||||
|
@apply m-0 p-0;
|
||||||
|
}
|
||||||
|
|
||||||
a { @apply text-white hover:text-secondary-400 focus-visible:text-secondary-400; }
|
a {
|
||||||
|
@apply text-white hover:text-secondary-400 focus-visible:text-secondary-400;
|
||||||
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
@apply inline-block mr-2;
|
@apply inline-block mr-2;
|
||||||
@@ -35,13 +51,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.contact__phone::before {
|
&.contact__phone::before {
|
||||||
background: url("../../static/img/footer-phone.svg") no-repeat center center;
|
background: url("../../static/img/footer-phone.svg") no-repeat
|
||||||
|
center center;
|
||||||
}
|
}
|
||||||
&.contact__email::before {
|
&.contact__email::before {
|
||||||
background: url("../../static/img/footer-email.svg") no-repeat center center;
|
background: url("../../static/img/footer-email.svg") no-repeat
|
||||||
|
center center;
|
||||||
}
|
}
|
||||||
&.contact__address::before {
|
&.contact__address::before {
|
||||||
background: url("../../static/img/footer-map.svg") no-repeat center center;
|
background: url("../../static/img/footer-map.svg") no-repeat center
|
||||||
|
center;
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,32 +68,118 @@
|
|||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.site-footer {
|
.site-footer {
|
||||||
padding-block: 2.25rem 1.25rem;
|
border-bottom-width: clamp(4.0625rem, 20.4vw, 5.125rem);
|
||||||
|
font-size: clamp(0.875rem, 3.98vw, 1rem);
|
||||||
|
min-height: clamp(34rem, 167.4vw, 42.0625rem);
|
||||||
|
padding-block: clamp(2.375rem, 11.94vw, 3rem)
|
||||||
|
clamp(1.125rem, calc(12.2vw - 1.3125rem), 1.75rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-footer > .container {
|
.site-footer > .container {
|
||||||
gap: 1.5rem 1rem;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
gap: 0 clamp(0.8125rem, 3.98vw, 1rem);
|
||||||
padding-inline: 1rem;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
padding-inline: clamp(1.59375rem, 7.96vw, 2rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-footer .site-footer__logo {
|
.site-footer > .container > div:first-child {
|
||||||
max-width: 6rem;
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-footer .widget li {
|
.site-footer #footer-header {
|
||||||
font-size: var(--text-14px);
|
margin: 0;
|
||||||
line-height: 1.1;
|
max-width: clamp(9.75rem, 48.76vw, 12.25rem);
|
||||||
margin-bottom: 0.4rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-footer .widget h4 {
|
.site-footer #footer-nav {
|
||||||
font-size: var(--text-16px);
|
grid-column: 1 / -1;
|
||||||
margin-bottom: 0.5rem;
|
grid-row: 2;
|
||||||
|
margin-top: clamp(1.5625rem, 7.71vw, 1.9375rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-footer .text-right {
|
.site-footer .site-footer__nav-list {
|
||||||
align-items: flex-start;
|
display: grid;
|
||||||
text-align: left;
|
gap: clamp(0.625rem, 3.23vw, 0.8125rem) clamp(1.59375rem, 7.96vw, 2rem);
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-template-rows: repeat(3, auto);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .site-footer__nav-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer #footer-nav + div {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-row: 3;
|
||||||
|
margin-top: clamp(1.25rem, 6.22vw, 1.5625rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer #footer-description {
|
||||||
|
font-size: clamp(1rem, 4.98vw, 1.25rem);
|
||||||
|
line-height: 1.2;
|
||||||
|
max-width: 21rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .contact__item {
|
||||||
|
font-size: clamp(0.75rem, 3.48vw, 0.875rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .contact__address {
|
||||||
|
margin-top: clamp(0.875rem, 4.48vw, 1.125rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .contact__email,
|
||||||
|
.site-footer .contact__phone {
|
||||||
|
margin-top: clamp(0.8125rem, 3.98vw, 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .contact__item::before {
|
||||||
|
height: clamp(1.1875rem, 5.97vw, 1.5rem);
|
||||||
|
margin-right: clamp(0.375rem, 1.99vw, 0.5rem);
|
||||||
|
width: clamp(1.1875rem, 5.97vw, 1.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .contact__address::before {
|
||||||
|
padding-top: clamp(1.59375rem, 7.96vw, 2rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer > .container > .text-right {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer x-back-to-top {
|
||||||
|
align-self: start;
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer #backToTopBtn {
|
||||||
|
height: clamp(2rem, 9.95vw, 2.5rem);
|
||||||
|
padding: 0;
|
||||||
|
width: clamp(2rem, 9.95vw, 2.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .social-links {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-row: 4;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: clamp(0.5rem, 2.49vw, 0.625rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .social-icons {
|
||||||
|
--size: clamp(1.1875rem, 5.97vw, 1.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .social-links a {
|
||||||
|
margin-right: clamp(0.8125rem, 3.98vw, 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer .copyright {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-row: 5;
|
||||||
|
margin-top: clamp(0.8125rem, 4.23vw, 1.0625rem);
|
||||||
|
padding-block: 0;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -697,6 +697,69 @@ test("configured footer channels use the prepared SVG icons", async ({
|
|||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("mobile footer matches the reference hierarchy", async ({ page }) => {
|
||||||
|
await page.goto(homepage);
|
||||||
|
|
||||||
|
const footer = page.locator(".site-footer");
|
||||||
|
const footerBox = await getBox(footer);
|
||||||
|
const logo = await getBox(footer.locator(".site-footer__logo-image"));
|
||||||
|
const backToTop = await getBox(footer.locator("#backToTopBtn"));
|
||||||
|
const nav = await getBox(footer.locator("#footer-nav"));
|
||||||
|
const contact = await getBox(footer.locator(".contact"));
|
||||||
|
|
||||||
|
expectNear(footerBox.height, 673, 12);
|
||||||
|
expectNear(logo.y, backToTop.y, 8);
|
||||||
|
expect(nav.y).toBeGreaterThan(logo.y + logo.height);
|
||||||
|
expect(contact.y).toBeGreaterThan(nav.y + nav.height);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("mobile footer scales down and remains contained", async ({ page }) => {
|
||||||
|
for (const width of [320, 767]) {
|
||||||
|
await page.setViewportSize({ width, height: 900 });
|
||||||
|
await page.goto(homepage);
|
||||||
|
|
||||||
|
const footer = page.locator(".site-footer");
|
||||||
|
const footerBox = await getBox(footer);
|
||||||
|
const logo = await getBox(footer.locator(".site-footer__logo-image"));
|
||||||
|
const backToTop = await getBox(footer.locator("#backToTopBtn"));
|
||||||
|
const nav = await getBox(footer.locator("#footer-nav"));
|
||||||
|
const contact = await getBox(footer.locator(".contact"));
|
||||||
|
const social = await getBox(footer.locator(".social-links"));
|
||||||
|
const copyright = await getBox(footer.locator(".copyright"));
|
||||||
|
const expectedHeight = Math.min(width, 402) * (673 / 402);
|
||||||
|
|
||||||
|
expectNear(footerBox.height, expectedHeight, 12);
|
||||||
|
expectNear(logo.y, backToTop.y, 8);
|
||||||
|
expect(nav.y).toBeGreaterThan(logo.y + logo.height);
|
||||||
|
expect(contact.y).toBeGreaterThan(nav.y + nav.height);
|
||||||
|
expect(social.y).toBeGreaterThan(contact.y + contact.height);
|
||||||
|
expect(copyright.y).toBeGreaterThan(social.y + social.height);
|
||||||
|
expect(footerBox.x).toBeGreaterThanOrEqual(0);
|
||||||
|
expect(footerBox.x + footerBox.width).toBeLessThanOrEqual(width);
|
||||||
|
expect(
|
||||||
|
await page.evaluate(() => document.documentElement.scrollWidth),
|
||||||
|
).toBeLessThanOrEqual(width);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("footer restores its four-column desktop layout at 768px", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await page.setViewportSize({ width: 768, height: 900 });
|
||||||
|
await page.goto(homepage);
|
||||||
|
|
||||||
|
const footer = page.locator(".site-footer");
|
||||||
|
const outer = footer.locator(":scope > .container");
|
||||||
|
|
||||||
|
await expect(footer).toHaveCSS("border-bottom-width", "16px");
|
||||||
|
await expect(footer).toHaveCSS("padding-top", "64px");
|
||||||
|
await expect(outer).toHaveCSS("grid-template-columns", /.+ .+ .+ .+/);
|
||||||
|
await expect(outer.locator(":scope > .text-right")).toHaveCSS(
|
||||||
|
"display",
|
||||||
|
"flex",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("mobile homepage has no automated accessibility violations", async ({
|
test("mobile homepage has no automated accessibility violations", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user