8

I'm trying to use position: sticky on a rotated element but I get extra space at the top. Also where the sticky element has to stops (at the end of parent) it goes outside.

Notice I need to have control to choose how many pixels put between sticky element and the left window side.

Check the 2 screenshot to understand the 2 problems, and what I want to achieve.

Problem 1: extra space at top State 1 (default at start)

Problem 2: sticky element goes outside at the end of section State 2 (at section end)

I'm using this code:

HTML

<section class="section">

  <h1 class="section__title">STICKY</h1>

  <div class="container">
    <div class="row">
      <div class="col [ col-lg-8 offset-lg-2 ]">
        <div class="h4">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam quos illum aperiam officia provident, mollitia at, tempore atque, blanditiis sit optio esse harum officiis voluptas iusto sequi. Magni, reiciendis quidem.
        </div>
      </div>
    </div>
  </div>

</section>

CSS

.section__title {
  display: inline-block;
  transform: rotate(-90deg) translatex(-100%);
  transform-origin: 0% 0%; 
  margin-bottom: 0;

  position: sticky;
  top: 0;
  left: 50px;
}

Here is a Codepen with the entire code: https://codepen.io/anon/pen/KLqJGG

How can I solve this? Thanks

Fred K
  • 13,249
  • 14
  • 78
  • 103

2 Answers2

7

Problem 1: extra space at top

The stickily positioned element stays in the DOM flow - just like a relative positioned element does. So, hence the space there, which is occupied by the h1.section__title element.

Problem 2: sticky element goes outside at the end of section

It is because, the original height of the h1 element is still considered there, even after rotation.

So, you need to determine the exact width of the sticky header (which then becomes the height of this element after rotation) first and then set this width value for the rotated element's height, as follows:

$section-sticky-header-height: 145px;

.section__title {
  display: inline-block;
  margin-bottom: 0;
  transform-origin: 0% 0%; 
  position: sticky;
  top: 0;
  left: 50px;

  /* solves problem 1 */
  float: left; 

  /* solves problem 2 */
  transform: rotate(-90deg) translatex(-$section-sticky-header-height);
  height: $section-sticky-header-height;
}

Codepen: https://codepen.io/anon/pen/arybWZ


Edit:

The problem is that I cannot determine the exact width of the sticky header because the h1 text is variable (the client will insert that text via a CMS). Is there a way to handle this? If possible without Javascript

Got it. You can try this instead, if the height is variable:

<h1 class="h1 mb-0 section__title">
  <div class="rotation-outer">
    <div class="rotation-inner">
      <div class="rotation">
        STICKY
      </div>
    </div>
  </div>
</h1>
.section__title {
  border: 1px solid; // for demo purpose
  position: sticky;
  top: 0;
  float: left;

  .rotation-outer {
    display: table;
    position: relative;
    left: 50px;

    .rotation-inner {
      padding: 50% 0;
      height: 0;

      .rotation {
        transform-origin: 0 0;
        transform: rotate(-90deg) translate(-100%);
        margin-top: -50%;
        white-space: nowrap; 
      }
    }  
  }
}

See in action: https://codepen.io/anon/pen/BedREm

There's a very good explanation here for how this works: Rotated elements in CSS that affect their parent's height correctly


Edit 2:

At that link I also discovered the writing-mode: vertical-rl; property (in this answer stackoverflow.com/a/50406895/1252920). Do you think could be a better solution? I applied it in this Codepen: codepen.io/anon/pen/JqyJWK?editors=1100 What do you think?

Yes, another sweet alternative, you can use. :)

Here I changed/optimized it a little bit: https://codepen.io/anon/pen/qGXPPe?editors=1100

However, please note that vertical-lr or vertical-rl is not widely supported. Apparently only on desktop version of Chrome/Firefox/Opera. See here. So, it's up to you, which one to use. Personally, I wouldn't use writing-mode due to lack of browser support.

  • Ok, we're almost there. The problem is that I cannot determine the exact width of the sticky header because the h1 text is variable (the client will insert that text via a CMS). Is there a way to handle this? If possible without Javascript (but if there isn't other solution we'll consider it) – Fred K May 19 '19 at 10:09
  • Oh man, what you did is pure witchcraft! I understand it only in part. Thanks. Just one thing: I noticed that the `margin-left` on `.section__title` moves the `.container`, while it should remains independent from sticky element. Is it possible? – Fred K May 19 '19 at 16:13
  • Huh, sorry about that. I updated my answer. Removed margin-left. Added `position: relative; left: 50px` to `.rotation-outer`. It should do it. –  May 19 '19 at 16:18
  • @FredK Please see the link I added for a detailed explanation. :) –  May 19 '19 at 16:22
  • 1
    Wow, awesome! Thanks so much! At that link I also discovered the `writing-mode: vertical-rl;` property (in this answer https://stackoverflow.com/a/50406895/1252920). Do you think could be a better solution? I applied it in this Codepen: https://codepen.io/anon/pen/JqyJWK?editors=1100 What do you think? – Fred K May 19 '19 at 17:00
  • @FredK Thanks for the feedback. You can find my answer in the post - updated. –  May 19 '19 at 19:21
  • About `vertical-rl` support I looked here https://caniuse.com/#feat=css-writing-mode and it actually seems supported by all except IE browsers. So I'm pretty confused, since your link from Mozilla says the opposite! Instead, about the first method, he says https://stackoverflow.com/a/47860039/1252920 that is not fully spec-compliant so it may be no longer supported in the future. Thinking about what is more secure... – Fred K May 20 '19 at 09:53
  • @FredK Unfortunately, I never used/needed `writing-mode` CSS property before. Thus, I can only recommend you to test it with multiple browsers (both desktop and mobile browsers). [Here](https://css-tricks.com/almanac/properties/w/writing-mode/) in the `Browser support` section it looks also promising. If you are happy with the test results, go for it! Otherwise I see no reason, why you shouldn't try the previous solution, since it also works too. –  May 20 '19 at 10:10
0

Seems to me that your Codepen does not have that padding you mention, therefore I wonder if you removed the default padding and margin of html and body elements.

html, body {
    margin: 0;
    padding: 0;
}

Let me know if it works or in which browser the padding you mention appears.

Silencesys
  • 545
  • 5
  • 12
  • I tried to add your CSS code but nothing changes. I see the issues on every browsers (Chrome, Firefox, Safari). Are you sure to understand what are the problems I'm experiencing? – Fred K May 18 '19 at 15:36
  • Sorry, I don't know how I read it, but I thought you want to achieve different thing. ‍♂️ Let me see, if I can help. What should definitely move the sticky element from top is setting the `top:` value in `.section__title` class, however it will not set the exact padding from top as the section have. – Silencesys May 18 '19 at 15:42
  • The only way I was able to remove the unwanted padding was by adding negative top margin to the .container class, please check this [Codepen](https://codepen.io/silencesys/pen/EzXMOW). I'll add it also to the answer if it will work for you. – Silencesys May 18 '19 at 15:52
  • Yes, already thought about "hardcoded" ways to move the container but they're dirty, in my opinion. Hoping in a better solution. Also I have the second problem (check the second screenshot in my question post). Thanks – Fred K May 18 '19 at 16:03
  • @FredK I have updated the [Codepen](https://codepen.io/silencesys/pen/EzXMOW) also for bottom padding. I wonder if there is cleaner solution, however the padding you want to remove is in fact the height of the sticky element. – Silencesys May 18 '19 at 16:14
  • Sorry, I have changed it once again, the top could be solved by changing the `transform-origin` but the bottom seems unsolvable. https://codepen.io/silencesys/pen/EzXMOW – Silencesys May 18 '19 at 16:38
  • If you check via inspector now there's an extra space both on container and sticky element. Anyway I'm searching for a solution to both the problems. Thanks – Fred K May 18 '19 at 16:53
  • I think this is because your sticky element is in a Heading element (

    )

    – Mister Jojo May 18 '19 at 18:07