I am trying to set elements (children of a container with transform) to fixed position relative to the viewport. I'm attempting to find each of them, and assign to a variable via getBoundingClientRect(), then define style properties from that variable.
<div>
<div >
<div>
<!-- Image -->
</div>
</div>
</div>
<div>
<div >
<div>
<!-- Image -->
</div>
</div>
</div>
<!-- more -->
JS v1
$('.preview-container').each(function(el) {
preview = this.getBoundingClientRect();
console.log(preview);
preview.style.position = "fixed";
preview.style.top = "0";
preview.style.left = "0";
});
This works without the three style lines and console displays all of the .preview-container elements correctly. Adding the style lines produces errors about those style properties not being defined:
jQuery.Deferred exception: Cannot set properties of undefined (setting 'position')Uncaught TypeError: Cannot set properties of undefined (setting 'position')
I don't understand that because preview is working in console.
JS v2
This attempt works as is, but is less complete. console is producing all of the .preview-container elements, but I haven't been able to incorporate getBoundingClientRect():
document.querySelectorAll(".preview-container").forEach(preview => {
preview.style.position = "fixed";
preview.style.top = "0";
preview.style.left = "0";
console.log(preview);
});
I feel like I am closer with JS v1, and am missing something simple with the style properties. How should I proceed?
CodePudding user response:
You have a problem with the name of your variables, in the first one you call it el and you refer as preview. And to get the values of getBoundingClientRect you need to create another variable.
document.querySelectorAll(".preview-container").forEach(preview => {
previewValues = preview.getBoundingClientRect();
preview.style.position = "fixed";
preview.style.top = "0";
preview.style.left = "0";
console.log(preview);
console.log(previewValues);}
)
<div>
<div >
<div>
<!-- Image -->
</div>
</div>
</div>
<div>
<div >
<div>
<!-- Image -->
</div>
</div>
</div>
<!-- more -->
CodePudding user response:
Looking at the interfaces for DOMRect (there are several), it states that updating properties of a DOMRect updates the position of the element it was called on, as in this example:
"use strict";
$('.preview-container').each(function(el) {
var rect = this.getBoundingClientRect();
this.style.position = "fixed";
// this.style.top = "0";
rect.x = 0;
// this.style.left = "0";
rect.y = 0;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- body-html -->
<div>
<div >
<div>
Image 1
</div>
</div>
</div>
<div>
<div >
<div>
Image 2
</div>
</div>
</div>
Note
thishas been used to refer to preview divisions in theeachargument function, notel.- Changes to position are made by setting properties of
rect, notstyle, as allowed in the standard, but this is uncommon. - Usually positions are set either in CSS, or using element
styleobjects (thethis.stylelines commented out above), without callinggetBoundingClientRectto obtain aDOMRectfirst.
However when an element descends from an element with a transform property, the transform element behaves as the containing block for fixed elements below as shown here:
$('.preview-container').each(function(el) {
this.style.position = "fixed";
this.style.top = "0";
this.style.left = "0";
});
/* CSS from https://developer.mozilla.org/en-US/docs/Web/CSS/transform */
div.ancestor {
border: solid red;
transform: translate(30px, 20px) rotate(20deg);
width: 140px;
height: 60px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- body-html -->
<div >
<div >
<div>
Image 1
</div>
</div>
</div>
<div >
<div >
<div>
Image 2
</div>
</div>
</div>
If you want to fix preview container positioning relative to the view port, try moving them out from under the transform ancestor by, say, appending them to the body element. If aspects of the transform operation need to be retained on moved preview containers, a suitable CSS transform would need to be separately applied to them after the move.
