Link to home
Start Free TrialLog in
Avatar of jfredrickson
jfredrickson

asked on

Add Border to Element Without Effecting Element Size

I am trying to add a border to an element using javascript without affecting the size of the element. Simply adding a 1px border adds 2px to both the width and height of the element causing other elements that are relatively positioned to the affected element to move around.

Is there any simple way with CSS to apply a border without affecting the size of the element? I have tried subtracting 2px from the width and height of the element as well as both negative and positive margins and paddings but they all seem to effect the size of the element in some way and I can't get it to remain constant as the new border is added.

I have also tried adding a new element and positioning it on top of the original element so that the border appears visually but is not actually on the original element. This works well but causes any content inside the original element to be hidden behind the new div so that it cannot be select (although it is still visible as the new div has no background-color).

I have tried playing with the z-index of both the original element and the new one on top of it but couldn't get that to work well.

Can anybody think of a way that this might be achieved without effecting the current elements on the page?
Avatar of bluefezteam
bluefezteam

if you have a div which is 100px x 100px with no border, and add a border then it becomes 102px x102px

So you apply a border and deducated 2px from the objects width and height.

according to what you right above you have tried it - but that is how it's done, I've done it loads of times.

You could try applying display:block; to the element see if that fixes the method
Avatar of jfredrickson

ASKER

What method do you use to subtract 2px from the height and the width? I am using the following:

element.style.border = "1px solid red";
element.style.width = (element.offsetWidth-2)+"px";
element.style.height = (element.offsetHeight-2)+"px";

When I look closely at it though it doesn't seem to be doing anything at all. Perhaps this isn't the appropriate way to change the height and width?
The main issue comes when two elements are floated next to each other. When the border is added to the first element the second one no longer has enough room to float next to it and gets forced to the next line. This is still happening using the above method.
that's crazy.

if you have enough room for 200px across a line and both boxes add up to a combined width of 200px then it will fit, by swapping 2px border and reduceing the width of the div by 2px amounts to the same thing. Are you sure the javascript isn't applying a whitespace element? this may give it a 'space' and cause the wrap...

Method for change I'd use is :

d = document.getElementById('THE-NAME-OF-THE-DIV');
d.style.width="98px"; // WAS 100PX
d.style.height="98px"; // WAS 100PX
d.style.border="solid black 1px";
Isn't that exactly what I had except that I am getting the height and width dynamically from the element? Since I don't know which element this will be used on it needs to be dynamic. Is that the correct way to do it?

What do you mean by the javascript applying a whitespace element?
If i write out html and include a whitespace (a line brean, space or similar) it can cause gaps that apply extra space around items, eg

---------------------------------------------------
<img src="1.jpg" /> <img src="2.jpg" />
---------------------------------------------------
<img src="1.jpg" />
<img src="1.jpg" />
---------------------------------------------------
<img src="1.jpg" /><img src="2.jpg" /> <<< here theres no gap between elements so when set to 100px each they are exactly 200px - with accidental spacing they may become 205px and that wont fit causing a wrap.

have you tried performing an ALERT() to see what values you are receiving when running this (element.offsetWidth-2)+"px";

any chance you can upload a link to what you have so far.
Here's the script being tested on a random cnet article:

http://purusstudios.com/files/tmp/random_cnet_article.html

As you can see adding the border to the moused-over element causes things to jump around quite a bit.

I've been outputting the before and after height and width to my Firebug console and it seems that it is able to update the style.width and style.height properties but that doesn't seem to actually do anything.
Ok I'll give this somethough - interesting project.

Did you know that the effect doesn't work in IE? Also, in FF at the moment, images start to get squished.

I'm wondering if a cleaner solution would be to generate a div to fit over the top that has the same bounding box -2px with a border - this way it hovers over the top of the item and won't interfere with the physical dimesions - have you noticed images twitch and go smaller, some divs end up on 2 lines, this is because the physical size is altering, that suggestion of laying the border over the top will mean NO reshaping...
Yup, that's exactly the problem. I tried adding the div on top and that worked perfectly except that it was made it impossible to select any text inside the original element because the new element was on top of it.

Here's a link to that demo:

http://purusstudios.com/files/tmp/v03.html

As you can see it works great until you are trying to select an element inside the current selected element.
Hmm - I'm in IE7 and I can select underlying text, double clicking selects all text in that 'area' could you not have the facility of when clicking on the element it's copied to clip board?

I'll test it in FF
Hmmm the last demo works better in IE than it does in FF - FF makes the border flash whenever you move the mouse.
Yup, I've almost got the full keyboard imprinted on my forehead by now.

Interesting that IE allows you to interact with an element that is behind another one. It seems that v03.html is working almost exactly as intended in IE, now if only I can figure out a way to make it work in standards compliant browers.
Hey guys,
How about this:
border-color: transparent;

Tadaaaa. :D

No more adding borders or resizing divs; just change the color of the border when you need to see it.
^ Not really an appropriate solution here. Just thought it was something to think about.
Do you mean applying that to every element on the page initially and then just changing the color for the currently selected element? This would require a full restyling of the entire page making it impossible to use on any randomly selected page.
No, I'm dumb. I wrote it before you I saw that you were going to be doing it on random pages that you don't create.

I think it would be awesome if you could create one semi-transparent div when the page was first loaded, then use javascript to set the height/width/position of that div above the element that you hover. As you stated in the question, this would get in the way if you tried to use the stuff below it.

Have you tried using javascript to fill in the overlay div with the innerHTML from the element you are hovering?
Not possible to do that in this instance as it would make all the objects spaced apart. The true solution is to float a clone opbject above the current object - however there's a cross browser issue (as always)
"Have you tried using javascript to fill in the overlay div with the innerHTML from the element you are hovering?"

Yeah that's what I've been considering doing but I'm not quite sure how to handle the selection of elements inside if they are now duplicated on the page. Perhaps I can just remove the entire duplicate div which should leave the mouse above the newly selected div anyway allowing it to be reselected. I'll have to see how that works.
Damn, that works nicely except that the copied content doesn't seem to retain the original styling and so shows up all jumbled on top of the original content. It does allow you to select interior elements, but not in a transparent way as if you were selecting the original elements.

I played around a bit with styling to see if I could simply hide the interior content and simply retain blank blocks in place of the content so that the user could still interact with it as if it were the content beneath it. But this didn't seem to work in the way that I am used to when doing image-replacement.

Attached is the code I tried. Without a way to emulate the interior content and retain exact styling while hiding the content beneath it this doesn't appear to be the transparent solution that I need. I'm wondering if there just isn't a way to make the content beneath the highlight div selectable without having to replicate it inside the highlight div.

        // Add the content from our original div so that it is selectable by the user
        highlight.innerHTML = element.innerHTML;
 
        // Loop through all the interior elements and hide all their actual content
        highlightElements = highlight.getElementsByTagName("*");
        for (i=0;i<highlightElements.length;i++) {
            highlightElements[i].style.display = "block";
            highlightElements[i].style.width = highlightElements[i].offsetWidth+"px";
            highlightElements[i].style.height = highlightElements[i].offsetHeight+"px";
            highlightElements[i].style.textIndent = "-5000px";
            highlightElements[i].style.overflow = "hidden";
        } 

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of jfredrickson
jfredrickson

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If I say one more thing, will it make an admin come and look at this stuff? I'm still new here.
If somebody does have to review this: jfredrickson solved his own problem, and should get his points back.

I just think it's an interesting project, and your solution is pretty awesome.
Here's what I think would make it awesomer:
Use black divs without borders that are very transparent. Make them stretch to every edge of the screen. When your mouse isn't over any element, make them fill up the whole screen.

Make them so subtle that people don't even realize they are there; the page will just look a little darker. Then when you hover over an element it will get brighter. Yeah?
Thanks for the feedback Keale2. That does sound like a nice idea but again we run into the problem of not being able to select elements that are behind the new divs.  It could perhaps work to darken the rest of the page when an element is selected because you can still remove them when you mouse out of the selected div, but if you cover up the entire page initially you won't be able to select anything (at least in non-IE browsers). It does sound like a nice way to highlight the currently selected element though so I'll definitely take a look at it to see if it is feasible. Thanks again.