I have been searching the answer to this question but haven't been able to find a valid one. Let's take the following web site as an example:
https://www.atlassian.com/devops
There's a pseudo element before the following element:
var e = document.querySelector('li[class=language-selector]');
e.getClientRects();
top: 9797
bottom: 9818
left: 78
right: 162
x: 78
y: 9797
width: 85
height: 21
The function window.getComputedStyle returns some values for top, bottom, left and etc:
window.getComputedStyle(e, ':before').top; //10.5
window.getComputedStyle(e, ':before').bottom; //-9.5
window.getComputedStyle(e, ':before').left; //-26
window.getComputedStyle(e, ':before').right; //90.6
window.getComputedStyle(e, ':before').x; //0
window.getComputedStyle(e, ':before').y; //0
window.getComputedStyle(e, ':before').width; //20
window.getComputedStyle(e, ':before').height; //20
At first it seems to be relative values to the base element, but if I check the other element from the same page, the behavior seems inconsistent:
var e3=document.querySelectorAll('blockquote[class="cite large-quote"]')[0];
top: 2303
bottom: 2408
left: 78
right: 1038
x: 78
y: 2303
width: 960
height: 105
The function window.getComputedStyle returns the followings:
window.getComputedStyle(e3, ':before').top; //-25
window.getComputedStyle(e3, ':before').bottom; //-50
window.getComputedStyle(e3, ':before').left; //0
window.getComputedStyle(e3, ':before').right; //889.25
window.getComputedStyle(e3, ':before').x; //0
window.getComputedStyle(e3, ':before').y; //0
window.getComputedStyle(e3, ':before').width; //70.75
window.getComputedStyle(e3, ':before').height; //180
For example, the top and bottom of the first pseudo element are 10.5 and -9.5 and (10.5) - (-9.5) is the height of the pseudo element (20).
The top and bottom of the second pseudo element are -25 and -50 but the height of the pseudo element is 180. They are both having "absolute" in their "position" attribute. So the behavior is inconsistent.
It'll be greatly appreciated if someone can shed some lights on how to obtain the position or coordinates of pseudo elements.
The css property bottom is not the same as a bounding rectangle's bottom property. The fact that the top and bottom css values end up being the height of the pseudo element in the first test is just coincidence.
The bounding rectangle bottom is calculated based on its y position and its height:
https://drafts.fxtf.org/geometry/#dom-domrectreadonly-domrect-bottom
The bottom attribute, on getting, must return max(y coordinate, y
coordinate + height dimension).
The css bottom property however is a position value. With an absolute positioned element:
https://www.w3.org/TR/CSS2/visuren.html#propdef-bottom
Like 'top', but specifies how far a box's bottom margin edge is offset
above the bottom of the box's containing block.
So you can't simply use the formula bottom-top to get the pseudo element's height. You have to take the closest positioned container element's height into account, in your case the blockquote.
So for the blockquote element: Its height is 105px. The top of the quote is 25px above the top, and its bottom is 50px below the bottom. With those values you get the pseudo element's height:
105 - -25 - -50 = 180
As for the coordinates: the x,y properties seem to be browser specific as they do not exist in Firefox, IE, etc. And I cannot find out what they are exactly supposed to hold. Also the ones on the bounding box are simply the left,top values.
So if you want to calculate the left, top values you would have to use its left, top values and take again into account the closest positioned parent's location
var rect = e.getClientRects();
var pseudoStyle = window.getComputedStyle(e, ':before');
//find the elements location in the page
//taking into account page scrolling
var top = rect.top + win.pageYOffset - document.documentElement.clientTop;
var left = rect.left + win.pageXOffset - document.documentElement.clientLeft;
//modify those with the pseudo element's to get its location
top += parseInt(pseudoStyle.top,10);
left += parseInt(pseudoStyle.left,10);
Related
I created a custom scrollbar behavior of a div that goes down based on calculated; height of parent and current position scrollTop.
However, when the content reaches the end, the div stays in the middle and does not go beyond the top: 100% (actually it's 85 to be precise) How can I calculate that the div actually goes to the bottom?
$('.carousel-items').scroll(function() {
var currY = $(this).scrollTop();
console.log(currY);
var postHeight = $(this).height();
var scrollHeight = $('.carousel-item').height();
var scrollPercent = (currY / (scrollHeight - postHeight)) * 100;
scrollPercent = Math.abs(scrollPercent);
$('.test').css('top', scrollPercent +"%" );
});
I tried multiplying the sum by 1000 instead of 100, but the items in the content are dynamically added. I am now in a test environment (experimenting with 4 items) but when the project finishes the items in it could be like 20..
As you can see in the image, the scrollbar is reaches the end but the blue T div stays at the middle.
enter image description here
I have a input type text
<input type="text">
Basically I am using javascript ClientRect to get caret details. ClientRect looks like this
[object ClientRect]
{
[functions]: ,
__proto__: { },
bottom: 540.7999877929687,
constructor: { },
height: 24,
left: 1034.5399169921875,
right: 1034.5399169921875,
top: 516.7999877929687,
width: 0
}
This is generated on everytext input.
left: 1034.5399169921875,
left: 1065.5399169921875,
left: 1078.5399169921875,
I want to convert this number to CSS units like px/%/rem/vh. So that I can put dynamic css. How to do it?
Try accessing the left position of your input and subtract the left position of your caret. This should give you an approximate width of the text in the input, if that's what you are looking for. You'll need to add an id or create a selector for your text input.
var inputElementRect = document.getElementById('YOURINPUTID').getBoundingClientRect()
var width = inputElementRect.left - caretRect.left
Those values are px by default .. so just add suffix as px to that value and use it.
<input type="text">
to get that value
let text = document.querySelector('input');
let values = text.getBoundingClientRect();
let top_value = values.top + 'px';
let bottom_value = values.bottom + 'px';
let width_value = values.width + 'px';
let height_value = values.height + 'px';
console.log('top: '+ top_value);
console.log('bottom: '+ bottom_value);
console.log('width: '+ width_value);
console.log('height: '+ height_value);
here properties other than width and height are relative to the view port ( top, bottom, left, right ) ,
so if scroll this values will changes ..
to get the perfect values even if scroll add this values with window.scrollX , window.scrollY or can use window.pageXOffset , window.pageYOffset
So if I understand the question correctly, you have position values for the cursor inside of the input and you want to convert it into different types of CSS units, presumably so you can do something to the input or related things
The first thing to understand is that ClientRect positions are relative to the viewport. So as vhutchinson pointed out, if you want the width of text you need to compare to the input's "left" value as defined by getBoundingClientRects. That's a good start, but if you're not just influencing left but also care about top, you need to account for scrolling. If your window/page is the only scrolling container, you should be able to do this simply by adding window.scrollY to top, and window.scrollX to left to understand your offset relative to the window.
All of these units are pixels by default... if you want to convert to rem it's pretty straightforward, 1 rem = the font-size of your root element, so to convert to rem you can do something like
var remBase = parseInt(window.getComputedStyle(document.body).getPropertyValue('font-size'), 10);
var remValue = (myComputedPixelValue / remBase) + "rem";
Doing VW is similar using the answer in Get the browser viewport dimensions with JavaScript for cross-browser window dimensions, you'd end up with something that looks like
var viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var vwValue = (myComputedPixelValue / viewportWidth) + "vw";
Percentages are trickier, because you'd need to compute it based on the parent of the element you're applying the css value to, but the general idea follows the same principle.
I have div called first which width can be dynamic and horizontally centered according margin left right to auto
.first
{
width:70%;
background-color:#5b9a68;
position:relative;
margin:0 auto;
}
Another div second with position fixed
.second
{
position:fixed;
background-color:black;
color:white;
left:input;
}
Html
<div class="first">content</div>
<div class="second">Left Value</div>
i want this second div to position according to first div.The Problem here is second div position is fixed so it is positioning according to screen width so i tried this script to position it according to first div.
$(document).ready(function(){
var input=0;
var first_width = $(".first").width() / $('.first').parent().width() * 100;
var pos = (100-first_width)/2;//getting the empty part
var ex_pos=pos+input;
$('.second').css("left",ex_pos+"%");
});
Here when the input is zero it should start at the start of first div this is fine but when we changed the input value am not getting accurate percentage positioning according to first div.
Let say for example if i give 50 as input then i'll place it on 65 but this way am not perfectly positioning in 50 of first div.Also if i give 100% as input this will go outside.
How to do this if input is 100 then the second div should be at the end of first div.
if the input is 50 it should be at middle of first like that.
Output With 0% left position
Output With 50% left position
Output With 100% left position
NOTE-I don't want to change or edit the css. i would like to do it in script alone.
Check Fiddle
Here you go :
$(document).ready(function () {
var input = 0,
firstWidth = $('.first').width(), // width of first div
secondWidth = $('.second').width(), // width of second div
offset = (input * (firstWidth - secondWidth)) / 100, // % to shift
leftPos = $('.first').offset().left; // left position of first div
$('.second').css("left", leftPos + offset);
});
JSFiddle
From jQuery API Documentation : Link
The .offset() method allows us to retrieve the current position of an element relative to the document.
It returns an object containing the properties top and left.
So :
leftPos = $('.first').offset().left;
This gives us the left co-ordinates for the .first div i.e the point where it starts.
I guess, you are looking for scenarios for 50% and 100% .
This should do it :
JS :
if(input===100){
ex_pos = ex_pos - 43;
}else if(input===50){
ex_pos = ex_pos - 13;
}
FIDDLE
I want to get the total offSetTop and the total offSetLeft of a child element which have many level of parent element and may be adding up.
Is that any shorthand way, besides of adding one by one in manual ways?
To provide an answer without jQuery:
var a = Element, b = 0, c = 0;
while (a) {
b += a.offsetLeft;
c += a.offsetTop;
a = a.offsetParent;
}
Where Element is your Element node for which you need an offsetLeft and offsetTop.
using jQuery: $( node ).offset() then .top and .left
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
If you need the bounding rectangle relative to the top-left corner of the document, just add the current scrolling position to the top and left properties (these can be obtained using window.scrollX and window.scrollY) to get a bounding rectangle which is independent from the current scrolling position.
let { left, top } = domNode.getBoundingClientRect();
left += window.scrollX;
top += window.scrollY;
Is this possible? I'm trying to find the x and y coordinates of the element in relation to the browser.
var position = $(this).position();
x = position.left;
y = position.right;
Doesn't work.
Is there any way to do this?
http://adamsaewitz.com/housing/
highlight the blue room 070
The problem lies in the fact that you are accessing the top/left of an area element.
The area element is not positioned where its coords say. This is handled behind the scenes by the dom/browser.
So you need to find the image that the area relates to and grab its offset.
var imgId = $(this).closest('map').attr('name');
var imgPos = $('#' + imgId).offset();
Then, you grab the coords attribute of the area and split it to get left/top/width and use those to pinpoint the location inside the image.
var coords = $(this).attr('coords').split(',');
var box = {
left: parseInt(coords[0],10),
top: parseInt(coords[1],10),
width: parseInt(coords[2],10)-parseInt(coords[0],10),
height: parseInt(coords[3],10)-parseInt(coords[1],10)
};
Take into consideration the width/height of the info box that appears (and since you animate it, take that into consideration as well) and you get to
x = imgPos.left + box.left + box.width/2 - 65; // 65 is the info width/2
y = imgPos.top + box.top -20 -160 -1; // 20 is the animation, 160 is the info height, 1 is a safe distance from the top
demo: http://www.jsfiddle.net/XBjwN/
Edit for updated question: Since you're using <area> it's a different story, and fetching from the coords attribute is much easier, like this:
var position = $(this).attr('coords').split(',');
x = +position[0] - 50;
y = +position[1] - 170;
The offsets are just to account for the hard-coded width/height of the tooltip itself. In addition to the above, you want to use top and left rather than margin-top and margin-left. Also to account for the #content <div>'s position in the page, give it a relative position for the tooltip to sit in, like this:
#content { position: relative; }
Then...instead of .after(), use .append() so it gets added inside that parent.
You can test the result here.
For original question:
The object .position() returns has top and left properties...but you want .offset() here anyway (it's relative to the document, where .position() is relative to the offset parent), so it should look like this:
var position = $(this).offset(),
x = position.left,
y = position.top; //not right!
Or this:
var position = $(this).offset();
var x = position.left;
var y = position.top;
...but without a single var comma-separated statement, or a var on each line, you're also creating (or trying to) global variables, which will blow up in IE.
$(document).ready(function () {
$('map').imageMapResize();
$('area').hover(function () {
$('.imgpopover').css({ "display": "block", "top": $(this).attr("coords").split(',')[1]+"px", "left": $(this).attr("coords").split(',')[0]+"px" })
$('.imgpopover label').text($(this).attr("title"))
}, )
});