How to prevent: pseudo-elements with dynamically random position when scrollbar appears?

When the scroll bar appears, the :pseudo

items inside relative

are element

no longer in the right place.

Instead, they just flow somewhere inside element

.

Let's say I have the following markup. As you can see, elements :pseudo

adhere nicely to the edges of the element.

Fragment where :pseudo

are located well if there is no scrollbar

.without-scroll-bar {
  border: 5px solid green;
  padding: 15px;
  position: relative;
}

.without-scroll-bar:before,
.without-scroll-bar:after {
  position: absolute;
  content: "";
  height: 20px;
  width: 20px;
}

.without-scroll-bar:before {
  border-top: 5px solid red;
  border-right: 5px solid red;
  top: -5px;right: -5px;
}

.without-scroll-bar:after {
  border-right: 5px solid red;
  border-bottom: 5px solid red;
  bottom: -5px;right: -5px;
}
      

<div class="without-scroll-bar">
  <p>This is just some example text.</p>
</div>
      

Run codeHide result


However, when I make it element

fixed max-height

, so if it reaches it, it shows the scrollbar. Items are :pseudo

no longer located. They just flow somewhere inside the container.

A snippet that is :pseudo

not marked as disabled

code {
  background: #ededed;
  padding: 3px;
}

.with-scroll-bar {
  border: 5px solid green;
  padding: 15px;
  position: relative;
  max-height: 300px;
  overflow-y: auto;
  overflow-x: hidden;
}

.with-scroll-bar:before,
.with-scroll-bar:after {
  position: absolute;
  content: "";
  height: 20px;
  width: 20px;
}

.with-scroll-bar:before {
  border-top: 5px solid red;
  border-right: 5px solid red;
  top: -5px;right: -5px;
}

.with-scroll-bar:after {
  border-right: 5px solid red;
  border-bottom: 5px solid red;
  bottom: -5px;right: -5px;
}
      

<div class="with-scroll-bar">
  <p>As you can see, the <code>:pseudo</code> elements are not in position anymore</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
</div>
      

Run codeHide result


  • How can I prevent this?
  • How can I make the layout I want also apply on elements

    with scrollbars?
  • Better yet, how can I make the elements :pseudo

    stay on the edges? Like the first snippet, but then also with a scrollbar on the container?

Oh, I must point out that I have no access to myself HTML

. So I can't just wrap around it div

and then add items :pseudo

to div

.

+3


source to share


3 answers


JavaScript

If you can use JavaScript, another way would be to use the wrap () function from jQuery and add the pseudo-elements later to that wrapper div. Therefore, you still don't need to change anything in your HTML structure as JavaScript will do it for you.

Js

$(".with-scroll-bar").wrap("<div id='wrapper' />");

      



$(".with-scroll-bar").wrap("<div id='wrapper' />");
      

body {
  height: 1000px;
}

code {
  background: #ededed;
  padding: 3px;
}

#wrapper {
  position: relative;
}

.with-scroll-bar {
  border: 5px solid green;
  padding: 15px;
  position: relative;
  max-height: 300px;
  overflow-y: auto;
  overflow-x: hidden;
}

#wrapper:before,
#wrapper:after {
  position: absolute;
  content: "";
  height: 20px;
  width: 20px;
  z-index: 1000;
}

#wrapper:before {
  top: 0;
  right: 0;
  border-top: 5px solid red;
  border-right: 5px solid red;
}

#wrapper:after {
  bottom: 0;
  right: 0;
  border-right: 5px solid red;
  border-bottom: 5px solid red;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>This is just some example text.</p>
<p>This is just some example text.</p>

<div class="with-scroll-bar">
  <p>As you can see, the <code>:pseudo</code> elements are not in position anymore</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
</div>
      

Run codeHide result


CSS

There is also another pure CSS solution, but this is very hacky. This only works in Chrome as far as I could see and it doesn't support dynamic div height. This means that if the scrollbar is missing, the layout will break.



body {
  height: 1000px;
  transform: translateZ(0);
}

code {
  background: #ededed;
  padding: 3px;
}

.with-scroll-bar {
  border: 5px solid green;
  padding: 15px;
  position: relative;
  max-height: 300px;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
}

.with-scroll-bar:before,
.with-scroll-bar:after {
  position: fixed;
  display: flex;
  align-self: flex-end;
  content: "";
  height: 20px;
  width: 20px;
}

.with-scroll-bar:before {
  border-top: 5px solid red;
  border-right: 5px solid red;
  margin-top: -20px;
  margin-left: 34px;
}

.with-scroll-bar:after {
  border-right: 5px solid red;
  border-bottom: 5px solid red;
  margin-top: 295px;
  margin-left: 34px;
}
      

<p>This is just some example text.</p>
<p>This is just some example text.</p>
<div class="with-scroll-bar">
  <p>As you can see, the <code>:pseudo</code> elements are not in position anymore</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
</div>
      

Run codeHide result


+1


source


The idea is that you need to skip using pseudo altogether. What you can do is add two elements, using Javascript

one at the beginning of the other at the end.

Since they are :Pseudo elements

never DOM bound, you need these elements to manipulate the positions of your newly added elements according to your requirements



Sample script

there are some edge cases in the above example and these two buttons are only for changing the height of your parent div. You will get the basic idea and have to correct them accordingly.

+1


source


As you can easily see, by making the pseudo-elements more visible (for example, on all four sides), they are laid out in the same way as when the maximum height is not reached: in the corners of the space that the element occupies, not at the top and bottom of its content.

Predictable layouts include position: fixed or, as in the following, placing pseudo-elements on a line. What are you using pseudo-elements for?

code {
  background: #ededed;
  padding: 3px;
}
 .with-scroll-bar p{
margin:15px;
}
.with-scroll-bar {
  border: 5px solid green;
  padding: 0px;
  position: relative;
  max-height: 300px;
  overflow-y: auto; 

}

.with-scroll-bar:before,
.with-scroll-bar:after {
  border: 5px solid red;
display:block;
    content: "";
  height: 20px;
  
 


}

  .with-scroll-bar:before 
 {

left:0px;
width:20px;
  margin:0px;


}   

.with-scroll-bar:after {
 
left:0px;
right:0px;
  margin:0px;


}
      

<div class="with-scroll-bar">
  <p>As you can see, the <code>:pseudo</code> elements are not in position anymore</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
  <p>This is just some example text.</p>
</div>
      

Run codeHide result


0


source







All Articles