4

I am using CSS to create subheads that stay stuck while scrolling until the next subhead comes along and nudges it out of the way, but (because I'm using rotated text) I'd like to somehow control (through padding, perhaps?) when the the subhead becomes "unstuck" so that the subheads don't overlap. Here's what I have:

.itemblock {
  background-color:  red;
  color: white;
  padding: 10px;
  margin-bottom: 10px;
  margin-left: 10px;
}

.subcategory {
  border-left: solid 20px blue;
}

.subhead {
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -o-sticky;
  position: -ms-sticky;
  position: sticky;
  color: white;
  display: block;
  height: 0px;
  scroll: hidden;
  top: 10px;
  left: -40px;
  margin-left: -18px;
  transform-origin: top left;
  transform: rotate(-90deg) translate(-20px);
}
<div class="subcategory">
  <div class="subhead">A</div>
  <div class="itemblock">Item A1</div>
  <div class="itemblock">Item A2</div>
  <div class="itemblock">Item A3</div>
  <div class="itemblock">Item A4</div>
  <div class="itemblock">Item A5</div>
  <div class="itemblock">Item A6</div>
  <div class="itemblock">Item A7</div>
  <div class="itemblock">Item A8</div>
  <div class="itemblock">Item A9</div>
</div>
<div class="subcategory">
  <div class="subhead">B</div>
  <div class="itemblock">Item B1</div>
  <div class="itemblock">Item B2</div>
  <div class="itemblock">Item B3</div>
  <div class="itemblock">Item B4</div>
  <div class="itemblock">Item B5</div>
  <div class="itemblock">Item B6</div>
  <div class="itemblock">Item B7</div>
  <div class="itemblock">Item B8</div>
  <div class="itemblock">Item B9</div>
</div>
<div class="subcategory">
  <div class="subhead">C</div>
  <div class="itemblock">Item C1</div>
  <div class="itemblock">Item C2</div>
  <div class="itemblock">Item C3</div>
  <div class="itemblock">Item C4</div>
  <div class="itemblock">Item C5</div>
  <div class="itemblock">Item C6</div>
  <div class="itemblock">Item C7</div>
  <div class="itemblock">Item C8</div>
  <div class="itemblock">Item C9</div>
</div>

If you scroll up, you'll see the "A" subhead stay stuck until the "B" subhead comes along, but the two overlap for a moment. I'd like to be able to have the "A" header become unstuck so it appears to stay within it's own blue area.

Of course, the problem is compounded with longer headers:

.itemblock {
  background-color:  red;
  color: white;
  padding: 10px;
  margin-bottom: 10px;
  margin-left: 10px;
}

.subcategory {
  border-left: solid 20px blue;
}

.subhead {
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -o-sticky;
  position: -ms-sticky;
  position: sticky;
  color: white;
  display: block;
  height: 0px;
  scroll: hidden;
  top: 10px;
  left: -40px;
  margin-left: -18px;
  transform-origin: top left;
  transform: rotate(-90deg) translate(-80px);
}
<div class="subcategory">
  <div class="subhead">Subhead A</div>
  <div class="itemblock">Item A1</div>
  <div class="itemblock">Item A2</div>
  <div class="itemblock">Item A3</div>
  <div class="itemblock">Item A4</div>
  <div class="itemblock">Item A5</div>
  <div class="itemblock">Item A6</div>
  <div class="itemblock">Item A7</div>
  <div class="itemblock">Item A8</div>
  <div class="itemblock">Item A9</div>
</div>
<div class="subcategory">
  <div class="subhead">Subhead B</div>
  <div class="itemblock">Item B1</div>
  <div class="itemblock">Item B2</div>
  <div class="itemblock">Item B3</div>
  <div class="itemblock">Item B4</div>
  <div class="itemblock">Item B5</div>
  <div class="itemblock">Item B6</div>
  <div class="itemblock">Item B7</div>
  <div class="itemblock">Item B8</div>
  <div class="itemblock">Item B9</div>
</div>
<div class="subcategory">
  <div class="subhead">Subhead C</div>
  <div class="itemblock">Item C1</div>
  <div class="itemblock">Item C2</div>
  <div class="itemblock">Item C3</div>
  <div class="itemblock">Item C4</div>
  <div class="itemblock">Item C5</div>
  <div class="itemblock">Item C6</div>
  <div class="itemblock">Item C7</div>
  <div class="itemblock">Item C8</div>
  <div class="itemblock">Item C9</div>
</div>

I recognize that this may just be pushing CSS too far. I'd really like to avoid any Javascript if I can, but if I have to go that route I will.

Any ideas?

2 Answers 2

4

You can use z-index to solve this:

  1. Added position: relative to the .subcategory to make sure we can apply the z-index
  2. Added z-index: 1 to the .subcategory
  3. Added z-index: 2 to the .subhead

.itemblock {
  background-color:  red;
  color: white;
  padding: 10px;
  margin-bottom: 10px;
  margin-left: 10px;
}

.subcategory {
  border-left: solid 20px blue;
  position: relative;
  z-index: 1;
}

.subhead {
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -o-sticky;
  position: -ms-sticky;
  position: sticky;
  color: white;
  display: block;
  height: 0px;
  scroll: hidden;
  top: 10px;
  left: -40px;
  margin-left: -18px;
  transform-origin: top left;
  transform: rotate(-90deg) translate(-80px);
  z-index: 2;
}
<div class="subcategory">
  <div class="subhead">Subhead A</div>
  <div class="itemblock">Item A1</div>
  <div class="itemblock">Item A2</div>
  <div class="itemblock">Item A3</div>
  <div class="itemblock">Item A4</div>
  <div class="itemblock">Item A5</div>
  <div class="itemblock">Item A6</div>
  <div class="itemblock">Item A7</div>
  <div class="itemblock">Item A8</div>
  <div class="itemblock">Item A9</div>
</div>
<div class="subcategory">
  <div class="subhead">Subhead B</div>
  <div class="itemblock">Item B1</div>
  <div class="itemblock">Item B2</div>
  <div class="itemblock">Item B3</div>
  <div class="itemblock">Item B4</div>
  <div class="itemblock">Item B5</div>
  <div class="itemblock">Item B6</div>
  <div class="itemblock">Item B7</div>
  <div class="itemblock">Item B8</div>
  <div class="itemblock">Item B9</div>
</div>
<div class="subcategory">
  <div class="subhead">Subhead C</div>
  <div class="itemblock">Item C1</div>
  <div class="itemblock">Item C2</div>
  <div class="itemblock">Item C3</div>
  <div class="itemblock">Item C4</div>
  <div class="itemblock">Item C5</div>
  <div class="itemblock">Item C6</div>
  <div class="itemblock">Item C7</div>
  <div class="itemblock">Item C8</div>
  <div class="itemblock">Item C9</div>
</div>

1
  • That's actually pretty inventive: it's taking advantage of the fact that the text color of .subhead matches the background. What I'd really like to do is create a buffer between .subheads so the text appears to be confined to the vertical bounds of .subcategory. But your solution is definitely a lot better than what I posted.
    – TobyRush
    Commented Aug 31, 2017 at 17:18
1

Okay, I've figured out a way to make it work: the height of .subhead is what determines when it will start scrolling away, but I had it set to 0 so that my first .itemblock would be flush with the top of .subcategory.

Since increasing height gives me the buffer I need, though, I did so but then put a negative margin-top on the first .itemblock to account for it.

.itemblock {
  background-color:  red;
  color: white;
  padding: 10px;
  margin-bottom: 10px;
  margin-left: 10px;
}

.itemblock:nth-child(2) {    /* added this to counteract         */
                             /* the increased height in .subhead */
  margin-top: -100px;
}

.subcategory {
  border-left: solid 20px blue;
  position: relative;
  z-index: 1;
}

.subhead {
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -o-sticky;
  position: -ms-sticky;
  position: sticky;
  color: white;
  display: block;
  height: 100px;    /* increased height here from 0px                  */
                    /* height will depend on the length of the subhead */
  scroll: hidden;
  top: 10px;
  left: -40px;
  margin-left: -18px;
  transform-origin: top left;
  transform: rotate(-90deg) translate(-80px);
  z-index: 2;
}
<div class="subcategory">
  <div class="subhead">Subhead A</div>
  <div class="itemblock">Item A1</div>
  <div class="itemblock">Item A2</div>
  <div class="itemblock">Item A3</div>
  <div class="itemblock">Item A4</div>
  <div class="itemblock">Item A5</div>
  <div class="itemblock">Item A6</div>
  <div class="itemblock">Item A7</div>
  <div class="itemblock">Item A8</div>
  <div class="itemblock">Item A9</div>
</div>
<div class="subcategory">
  <div class="subhead">Subhead B</div>
  <div class="itemblock">Item B1</div>
  <div class="itemblock">Item B2</div>
  <div class="itemblock">Item B3</div>
  <div class="itemblock">Item B4</div>
  <div class="itemblock">Item B5</div>
  <div class="itemblock">Item B6</div>
  <div class="itemblock">Item B7</div>
  <div class="itemblock">Item B8</div>
  <div class="itemblock">Item B9</div>
</div>
<div class="subcategory">
  <div class="subhead">Subhead C</div>
  <div class="itemblock">Item C1</div>
  <div class="itemblock">Item C2</div>
  <div class="itemblock">Item C3</div>
  <div class="itemblock">Item C4</div>
  <div class="itemblock">Item C5</div>
  <div class="itemblock">Item C6</div>
  <div class="itemblock">Item C7</div>
  <div class="itemblock">Item C8</div>
  <div class="itemblock">Item C9</div>
</div>

It's a tiny bit kludgy, since it doesn't automatically match the width of the text, but it works.

2
  • It would help if you put in a diff between this and your original post, or at least added some comments like /*changed*/ where your changes are.
    – Stephen P
    Commented Sep 1, 2017 at 17:15
  • Good idea, thanks. I've added some comments in the code.
    – TobyRush
    Commented Sep 1, 2017 at 19:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.