78

I am trying to do some comparison logic about the positions of HTML elements. I have a system that I think should work, but there is a problem.

In my code I compare the current left and top values of one absolutely positioned element to those of another (which may be moving) using inequality statements (> and <). The problem is that the feedback I get form document.getElementById(nameVar).style.left is in the form of a string (e.g. 200px) not a number (e.g. 200), so the comparisons don't work.

My question is, is there any way to turn the string into a number that I can manipulate the way I want to? Either by using an altered address or by preforming some procedure with the feedback once I get it.

Any help would be great.

QuinnFreedman
  • 2,242
  • 2
  • 25
  • 42
  • Regex way: `"10px".replace(/[^0-9\.]+/g,'')|0` → `10` **or** `"10.px".match(/\d+/)[0]` – vsync Jul 01 '18 at 11:18

5 Answers5

109

parseInt gives you the numerical value:

var tmp = parseInt(document.getElementById(nameVar).style.left, 10);
console.log(tmp);

or, as @PeteWilson suggests in the comments, use parseFloat

konsolenfreddy
  • 9,551
  • 1
  • 25
  • 36
  • 14
    One further wrinkle: sometimes x and y values are kept in partial pixels (at least on my XP machine in Firefox and Chrome). parseInt( ) chokes on those things. Instead of parseInt( ), I found I had to use parseFloat( ) which works great and has the added virtue of handling whole numbers, too. Maybe this is just an accident arising from my particular setup. But I've had this code running for six months and haven't had a problem. You might want to consider using parseFloat(). – Pete Wilson Dec 31 '11 at 21:00
  • 5
    I think document.getElementById(nameVar).style.left.replace('px','') is a little more efficient – Ivan Castellanos Dec 31 '11 at 21:09
  • 8
    If you use [`parseInt`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt), please make sure to pass `10` as the 2nd parameter. Behavior isn't always predictable when it's not passed. `parseInt(x, 10)`. – gen_Eric Dec 31 '11 at 21:13
  • 9
    @IvanCastellanos 1) don't microoptimize; 2) that still leaves it as a string, not a number, so e.g. `result + 5` becomes `"2005"` instead of `205`. – Domenic Dec 31 '11 at 21:55
17

An alternative approach to the one from Konsolenfreddy, is to use:

var numericValue = window
    .getComputedStyle(document.getElementById('div'),null)
    .getPropertyValue('left')
    .match(/\d+/);

JS Fiddle demo.

The benefit of this approach is that it works to retrieve the value set in CSS, regardless of that value being set in the style attribute of the element or in a linked stylesheet, which I think Konsolenfreddy's approach is limited by.

References:

BSMP
  • 4,596
  • 8
  • 33
  • 44
David Thomas
  • 249,100
  • 51
  • 377
  • 410
9

You can use .offsetLeft and .offsetTop to get values without px and the return type is numeric.

Demo: http://jsfiddle.net/ThinkingStiff/2sbvL/

Script:

var result = document.getElementById( 'result' ),
    position = document.getElementById( 'position' );

result.textContent = position.offsetLeft + ', ' + position.offsetTop;

HTML:

<div id="position"></div>
<div id="result"></div>

CSS:

#position {
    border: 1px solid black;
    height: 50px;
    left: 50px;
    position: absolute;
    top: 50px;
    width: 50px;
}

Output:

enter image description here

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
  • 2
    If you are using CSS transition, the offsetLeft is different from the style.left property when the div is moving. Sorry for the downvote. – M'sieur Toph' Oct 17 '16 at 23:44
7

You may also use:

element.getBoundingClientRect()

it returns DOMRect object (with some useful coordinates).

Martin Melichar
  • 1,036
  • 2
  • 10
  • 14
0

Just solved this issue with TypeScript:

const parseCSSNumericValue = (value: string, unit: string): number | undefined => {
    const match = value.match(new RegExp(`(-?\\d+)${unit}`))
    if (!match) return
    const [, g1] = match
    return Number(g1)
}

You have to provide a value like '10px' and a unit you want to catch, like 'px'.

const [x] = getComputedStyle(element).backgroundPosition.split(' ')
const pixels = parseCSSNumericValue(x, 'px')

It's because you do not want to get 10 when you want to parse pixels but there is a '10%'.