0

Please consider the following HTML+CSS:

function adjust() {
  const target = document.getElementById('target');
  const follower = document.getElementById('follower');
  follower.parentElement.style.position = 'relative';
  follower.style.position = 'relative';
  follower.style.top = target.offsetTop + 'px';
  follower.style.height = target.offsetHeight + 'px';
}
.parent {
  display: grid;
  grid-template-columns: 100px 1fr;
  grid-template-rows: 1fr;
  grid-column-gap: 0px;
  grid-row-gap: 0px;
}

.sideline {
  grid-area: 1 / 1 / 1 / 1;
}

.essay {
  grid-area: 1 / 2 / 1 / 2;
  position: relative;
}

#target {
  background-color: yellow;
}

#follower {
  background-color: yellow;
}
<button onclick="adjust()">Adjust</button>
<div class="parent">
  <div class="sideline">
    <div id="follower">Sidenote</div>
  </div>
  <div class="essay">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ut malesuada erat. Nulla iaculis, justo eu consequat placerat, ex purus fringilla quam, nec molestie diam felis in dui. Etiam ut tincidunt risus, nec maximus velit. Vestibulum elementum
    tristique nisl, in aliquet sem fringilla quis. In turpis est, cursus a placerat quis, ultrices vel augue. Ut a risus rhoncus mi tempor bibendum vitae sit amet sem. Morbi eget mi ultricies, sodales nisl in, sollicitudin dolor.
    <span id="target">Vivamus luctus efficitur libero eu laoreet. Nunc id erat sed nunc hendrerit iaculis non ut quam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </span> Fusce ut dolor eget orci semper vulputate vel ut erat.
  </div>
</div>

Is there a pure-CSS solution how to position and vertically size the #follower so that it is spans the same vertical area as the #target element? There is no doubt it can be done by running some JavaScript (as demonstrated by the "Adjust" button), but it has to be run every time the window is resized. But is there a way how to rely on CSS to do it instead?

dale landry
  • 7,831
  • 2
  • 16
  • 28
Passiday
  • 7,573
  • 8
  • 42
  • 61
  • Looks quirky to me, unless I don't get it. But answering your question, how about putting the same content to the Sidenote one, with `user-select: none` and hide it? – Robo Robok Oct 22 '22 at 10:38
  • I may be misunderstanding, but I can’t see the target element. – A Haworth Oct 22 '22 at 11:56

1 Answers1

0

One way to do it is by using ::before pseudo element and the concept of relative and absolute positioning, One major issue with this solution is it requires you to use paragraphs for #target element.

Also if you only want to display Sidenote for the target element you can consider using title attribute to render Sidenote on hover and if you want to style the title text refer to this answer Styled Title Attribute.

.parent {
display: grid;
grid-template-columns: 100px 1fr;
grid-template-rows: 1fr;
grid-column-gap: 0px;
grid-row-gap: 0px;
}

.sideline { grid-area: 1 / 1 / 1 / 1; }
.essay { grid-area: 1 / 2 / 1 / 2; }

#target {
  background-color: yellow;
  position: relative;
}
#target::before {
  content: 'Sidenote';
  position: absolute;
  left: -100px;
  background-color: yellow;
  width: 100px;   
}
#follower {
  background-color: yellow;
}
  
<div class="parent">
<div class="sideline">
</div>
<div class="essay">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ut malesuada erat. Nulla iaculis, justo eu consequat placerat, ex purus fringilla quam, nec molestie diam felis in dui. Etiam ut tincidunt risus, nec maximus velit. Vestibulum elementum tristique nisl, in aliquet sem fringilla quis. In turpis est, cursus a placerat quis, ultrices vel augue. Ut a risus rhoncus mi tempor bibendum vitae sit amet sem. Morbi eget mi ultricies, sodales nisl in, sollicitudin dolor. <p id="target">Vivamus luctus efficitur libero eu laoreet. Nunc id erat sed nunc hendrerit iaculis non ut quam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p> Fusce ut dolor eget orci semper vulputate vel ut erat.
</div>
</div>
Raghav Joshi
  • 143
  • 1
  • 8