2

I am working on a website that has a footer element with decorations attached to its top edge in both ::before and ::after pseudo-elements (extending outside the footer element's bounding box), and I want only that top-edge-with-decorations to stick to the very bottom of the viewport until the user scrolls to the bottom of the page and the rest of the footer comes into view.

I can make it work if I hardcode the height of the footer element — for example, if I know the footer's bounding box is exactly 92 pixels tall (excluding the overflowing decorations), then the CSS rules position: sticky; bottom: -92px achieve exactly what I want. However, on the actual website the content of the footer differs between pages and may be updated and/or resized in the future, so I'd like to make the footer's stickiness responsive instead of hardcoded.

When percentages are used in the bottom property they are treated as a percentage of the containing block, not the element being positioned, so something like bottom: -100% doesn't work, and I haven't been able to find a calc() setup that can subtract the footer's dynamic height from the page height in this case.

I'm open to alternatives to position: sticky if there's an easier way to achieve the same effect. I'd like to make it work without changing the HTML structure (e.g. without adding wrapper elements) because I only currently have access to the CSS and getting permission to change the HTML would likely be an ordeal. JavaScript is also restricted for security reasons.

Below is a mock-up of the effect I want, currently using a hardcoded footer height that should make only the gold border and gray decorations be visible until you scroll all the way to the bottom, at which point the light-gray footer itself should come into view.

:root {
    --border-thickness: 1px;
    --border-color: gold;
}
body {
    margin: 0;
  line-height: 1.5;
}
header {
    background: gainsboro;
    position: sticky;
    top: 0;
    padding: 0.5rem 2rem 0.75rem;
    text-align: center;
}
main {
    margin: 0 2rem 2rem;
}
footer {
    background: gainsboro;
    position: sticky;
    bottom: -92px; /* Hardcoded footer-height offset that I want to make responsive */
    padding: 0.75rem 2rem 0.5rem;
    text-align: center;
}
header::after, footer::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    pointer-events: none;
    overflow: visible;
    height: calc(100% + 1.5rem);
    background: linear-gradient(to right, var(--border-color), var(--border-color)) no-repeat;
    background-size: 100% var(--border-thickness);
    filter: drop-shadow(0 0 0.5rem var(--border-color)) drop-shadow(0 0 0.5rem rgb(from var(--border-color) r g b / 0.25));
}
header::after {
    top: 0;
    background-position: center calc(100% - 1.5rem + var(--border-thickness));
}
footer::after {
    bottom: 0;
    background-position: center calc(0% + 1.5rem - var(--border-thickness));
}
footer::before {
    content: "";
    pointer-events: none;
    display: block;
    position: absolute;
    top: -36px; /* Decoration height */
    left: 0;
    width: 100%;
    height: 36px; /* Decoration height */
    background: gray;
    mask:
        url("https://i.sstatic.net/ZdOiZWmS.png") 0 0,
        url("https://i.sstatic.net/XxvJSPcg.png") 100% 0;
    mask-size: 140px auto, 224px auto; /* Decoration widths */
    mask-repeat: no-repeat;
}
<body>
    <header>
        Site Header
    </header>
    <main>
        <h1>Long Text to Scroll Past</h1>
        <p>Non eram nescius, Brute, cum, quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent, ea Latinis litteris mandaremus, fore ut hic noster labor in varias reprehensiones incurreret. nam quibusdam, et iis quidem non admodum indoctis, totum hoc displicet philosophari. quidam autem non tam id reprehendunt, si remissius agatur, sed tantum studium tamque multam operam ponendam in eo non arbitrantur. erunt etiam, et ii quidem eruditi Graecis litteris, contemnentes Latinas, qui se dicant in Graecis legendis operam malle consumere. postremo aliquos futuros suspicor, qui me ad alias litteras vocent, genus hoc scribendi, etsi sit elegans, personae tamen et dignitatis esse negent.</p>
        <p>Contra quos omnis dicendum breviter existimo. Quamquam philosophiae quidem vituperatoribus satis responsum est eo libro, quo a nobis philosophia defensa et collaudata est, cum esset accusata et vituperata ab Hortensio. qui liber cum et tibi probatus videretur et iis, quos ego posse iudicare arbitrarer, plura suscepi veritus ne movere hominum studia viderer, retinere non posse. Qui autem, si maxime hoc placeat, moderatius tamen id volunt fieri, difficilem quandam temperantiam postulant in eo, quod semel admissum coerceri reprimique non potest, ut propemodum iustioribus utamur illis, qui omnino avocent a philosophia, quam his, qui rebus infinitis modum constituant in reque eo meliore, quo maior sit, mediocritatem desiderent.</p>
        <p>Sive enim ad sapientiam perveniri potest, non paranda nobis solum ea, sed fruenda etiam sapientia est; sive hoc difficile est, tamen nec modus est ullus investigandi veri, nisi inveneris, et quaerendi defatigatio turpis est, cum id, quod quaeritur, sit pulcherrimum. etenim si delectamur, cum scribimus, quis est tam invidus, qui ab eo nos abducat? sin laboramus, quis est, qui alienae modum statuat industriae? nam ut Terentianus Chremes non inhumanus, qui novum vicinum non vult 'fodere aut arare aut aliquid ferre denique' non enim illum ab industria, sed ab inliberali labore deterret, sic isti curiosi, quos offendit noster minime nobis iniucundus labor.</p>
    </main>
    <footer>
        Site Footer <br>
        © 45 BC Marcus Tullius Cicero <br>
        <a href="#">Other Work</a> | <a href="#">Contact</a> | <a href="#">Donate</a>
    </footer>
</body>

3
  • 1
    bottom:0; transform: translateY(-100%); ? Can't remember off the top of my head if it's 100 or -100 Commented 2 days ago
  • @Pete I just tested this and the positive value does achieve the effect I want, but it also adds empty space (equal to the height of the footer) after the end of <main> and before the top of the footer once you scroll all the way down. Is there a way to avoid that? Commented 2 days ago
  • A little bit of javascript won't hurt in this case Commented 2 days ago

2 Answers 2

0

Add the decoration to the main element instead. I removed most of the CSS to keep the relevant one to the trick

body {
  margin: 0;
  line-height: 1.5;
}

header {
  background: gainsboro;
  position: sticky;
  top: 0;
  padding: 0.5rem 2rem 0.75rem;
  text-align: center;
}

main {
  margin: 0 2rem 2rem;
}

footer {
  background: gainsboro;
  position: sticky;
  padding: 0.75rem 2rem 0.5rem;
  text-align: center;
}

main::after {
  content: "";
  pointer-events: none;
  display: block;
  margin: -36px -2rem -2rem;
  height: 36px;
  position: sticky;
  bottom: 0;
  background: gray;
  mask:
    url("https://i.sstatic.net/ZdOiZWmS.png") 0 0,
    url("https://i.sstatic.net/XxvJSPcg.png") 100% 0;
  mask-size: 140px auto, 224px auto;
  mask-repeat: no-repeat;
}
<header>
  Site Header
</header>
<main>
  <h1>Long Text to Scroll Past</h1>
  <p>Non eram nescius, Brute, cum, quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent, ea Latinis litteris mandaremus, fore ut hic noster labor in varias reprehensiones incurreret. nam quibusdam, et iis quidem non admodum indoctis, totum hoc displicet philosophari. quidam autem non tam id reprehendunt, si remissius agatur, sed tantum studium tamque multam operam ponendam in eo non arbitrantur. erunt etiam, et ii quidem eruditi Graecis litteris, contemnentes Latinas, qui se dicant in Graecis legendis operam malle consumere. postremo aliquos futuros suspicor, qui me ad alias litteras vocent, genus hoc scribendi, etsi sit elegans, personae tamen et dignitatis esse negent.</p>
  <p>Contra quos omnis dicendum breviter existimo. Quamquam philosophiae quidem vituperatoribus satis responsum est eo libro, quo a nobis philosophia defensa et collaudata est, cum esset accusata et vituperata ab Hortensio. qui liber cum et tibi probatus videretur et iis, quos ego posse iudicare arbitrarer, plura suscepi veritus ne movere hominum studia viderer, retinere non posse. Qui autem, si maxime hoc placeat, moderatius tamen id volunt fieri, difficilem quandam temperantiam postulant in eo, quod semel admissum coerceri reprimique non potest, ut propemodum iustioribus utamur illis, qui omnino avocent a philosophia, quam his, qui rebus infinitis modum constituant in reque eo meliore, quo maior sit, mediocritatem desiderent.</p>
  <p>Sive enim ad sapientiam perveniri potest, non paranda nobis solum ea, sed fruenda etiam sapientia est; sive hoc difficile est, tamen nec modus est ullus investigandi veri, nisi inveneris, et quaerendi defatigatio turpis est, cum id, quod quaeritur, sit pulcherrimum. etenim si delectamur, cum scribimus, quis est tam invidus, qui ab eo nos abducat? sin laboramus, quis est, qui alienae modum statuat industriae? nam ut Terentianus Chremes non inhumanus, qui novum vicinum non vult 'fodere aut arare aut aliquid ferre denique' non enim illum ab industria, sed ab inliberali labore deterret, sic isti curiosi, quos offendit noster minime nobis iniucundus labor.</p>
</main>
<footer>
  Site Footer <br>
        © 45 BC Marcus Tullius Cicero <br>
  <a href="#">Other Work</a> | <a href="#">Contact</a> | <a href="#">Donate</a>
</footer>

Sign up to request clarification or add additional context in comments.

1 Comment

I'm running into two problems with this: first, Firefox says that negative margins on the main::after (and negative values for left and right and for the mask positions also) are invalid and ignores them, which means the decoration images are inset by the amount of main's margins; and second, the sticky-positioning only seems to work for the ::after pseudo-element, but I need both pseudo-elements to be sticky in order to have the decoration images AND the gold-line decoration that you removed from your answer. Are there ways to get around these issues?
0

A dynamically sized footer could be achieved with the following adjustments:

Add a surrogate element ".footer-inner", the ::before and ::after will be applied to this child, not the footer tag:

        <footer>
            <div class='footer-inner'>
                Site Footer <br>
                ....footer....
            </div>
        </footer>

Replace all footer:before's with footer .footer-inner:

/* for example */
footer::after {
/* becomes */
footer .footer-inner::after {

The <footer> is positioned at the bottom of the UI:

footer {
    text-align: center;
    position: sticky;
    bottom: 0;
}

And .footer-inner is positioned 100% from it's the top of it's closest non-static positioned parent (the <footer>):

footer .footer-inner{
    position:absolute;
    top:100%;
    width:100%; /* once absolute this block element will tight wrap like an inline element */
    box-sizing:border-box; /* added to ensure position the footer's content is positioned correctly */
    background: gainsboro;
    padding: 0.75rem 2rem 0.5rem;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.