Fit div to size of contents without overlapping text? - javascript

I am a very new (see: about a week) CSS user trying to do something that I think is pretty simple. I'm trying to (in a paragraph of text) post an image that is a help icon, that will display more information when you hover over it.
I'm having a bit of a problem with getting my divs to align correctly. I'd like the div containing the picture to only trigger when you hover over the help icon itself, not the entire line it's on. On my code (although not exactly in jsfiddle), I can do this with positioning it absolutely, however this causes the text below it to be overlapped when you use the hover. If I position it any other way, it doesn't overlap, but it isn't fit to the picture. It's back to only working on the entire line.
Is there a way to both fit a div to its contents (a small ~25x25 help icon) and then cause the hover below to not overlap what's under it? I'm trying to keep it on just css.
http://jsfiddle.net/YbGE6/ <--- Very basic jsfiddle format.
<div id = "Big">
<div id = "one"> "Hover" <div id="two"> "Hover text" </div></div></div>

Change the CSS for the div with the help icon to include display: inline-block;, which will cause it to fit its contents. div is by default display: block; which stretches across the entire line. Do not position the div absolutely, use the default static position, and have it float to wherever you want. The text will flow around it, and when the size of the help div changes on hover, it will push the text aside and the text will reflow around it.
Here is some documentation for float: https://developer.mozilla.org/en-US/docs/Web/CSS/float

Related

Why does displaying text inside the document via transform: translateY(-100%) create extra white-space at bottom of page?

Put very briefly
I wrote a vuejs component that includes a small icon that displays some text when being hovered over.
I created a minimal example here: https://codesandbox.io/s/sweet-jackson-v0kgc?file=/src/components/ShowBox.vue:115-136
The special thing is: when the icon is at the very bottom of the page the text is displayed above the icon instead of below such that the page does not have to be extended.
However, even when the text is displayed above the icon, the page is extended without any content (even the html ends before the whitespace).
I tested this in Firefox and Chromium.
I would like to understand where this white-space comes from and how to get rid of it.
I will explain in more detail what I'm trying to do below.
If my entire approach to this does not make much sense I'm also happy for suggestions.
My approach so far
First step: display text when hovering an image
What I want to achieve seems quite straight forward with vuejs at first glance.
I want to have a vue component that shows an image (for example a small info icon).
When one hovers over the image with the mouse a text is displayed that overlays the other content on the page.
This can be achieved in different ways - for example:
Create a component that has a hovered variable like so
<script>
export default {
name: 'ShowBox',
props: ['showText'],
data() {
return {
hovered: false,
}
},
}
</script>
In the template, bind the class of the to be shown text to the hovered variable and handle an #mouseenter and #mouseleave event in the image accordingly like so
<template>
<div class="show-box">
<div class="show-icon">
<img width="50px" #mouseenter="hovered = true" #mouseleave="hovered = false" src="...">
</div>
<div class="show-text" v-bind:class="{'hide': !hovered}">
{{ showText }}
</div>
</div>
</template>
Finally, in the style the class show-box should be positioned and the class show-text should include a position: absolute such that it overlays the text.
The class hide should somehow hide the text - for example with opacity: 0.
So far so good - for sure one can add a lot of stuff to make this more decent but for the sake of the example let's keep it simple.
The result might look as
this (link to picture).
Second step: display image above the icon when at the bottom of the page
Let's imagine the icon is at the very bottom of the page.
If one then hovers the icon the page might have to be extended in order to display the full text.
I want to avoid this and have the text displayed above the icon instead.
For this I took the following steps:
I wrapped the text in an extra div.
The text is now not rendered anymore when the page loads but only when one hovers over the image though a display: none in the style.
<template>
<div class="show-box">
<div class="show-icon">
<img width="50px" #mouseenter="hovered = true, , textRendered = true" #mouseleave="hovered = false" src="...">
</div>
<div class="show-text-wrap">
<div class="show-text" v-bind:class="{'not-rendered': !textRendered, 'hide': !hovered, 'render-top': renderTop}">
{{ showText }}
</div>
</div>
</div>
</template>
Furthermore, I included a life-cycle hook mounted such that after the page is rendered it is checked, whether there is enough space below the show-text-wrap div to display the text.
If not, a variable renderTop = true is set.
The style of the show-text div is now also bound to the renderTop variable such that if it is set (in the case of insufficient space at the botton of the page) the image is rendered above the icon (also see template above).
The mounted hook looks like
mounted() {
this.$nextTick(function () { //to be sure that page is fully rendered
var el = this.$el.lastElementChild; //show-text-wrap element
var rect = el.getBoundingClientRect();
if (rect.bottom + window.pageYOffset + 300 > (document.body.clientHeight)) {
this.renderTop = true;
}
}
)
},
Finally, the render-top class simply translates the text to the top.
.render-top{
transform: translateY(-100%);
}
The result when hovering over an icon at the bottom of the page might look like
this (link to picture).
The problem
This works fine in principle.
The only problem is: when the text is moved to the top as intended, some extra unwanted white-space appears at the bottom of the page (tested in Firefox and Chromium).
The white-space interestingly extends the html document.
I don't understand where this comes from and want to get rid of this since the whole point of moving the displayed text to the top was to avoid the page being extended.
In
this (link to image)
one can see the extra white-space that extends beyond the html document.
I also tried to move the text above the icon by different means for example
.render-top{
bottom: 0;
}
or even with hard coding pixel numbers like
.render-top{
bottom: 100px;
}
but none of these solve the problem.
I created a working minimal example for this https://codesandbox.io/s/sweet-jackson-v0kgc?file=/src/components/ShowBox.vue:115-136
where the problem can also be seen.
Any help is greatly appreciated - many thanks in advance!
A relative positioned element behaves as if it hadn't been moved
By now I found out the answer myself.
I will post it in case someone finds this useful.
The goal was to always move the text-box inside the viewport.
However, in the style the show-box's position was defined as position: relative; and only its direct parent show-text-wrap is absolutely positioned.
According to https://developer.mozilla.org/en-US/docs/Web/CSS/position a relative positioned element is offset relative to its original position.
This will not change the position of any other elements in the document.
This means that the layout of the document will behave as if the element was still at its original position.
Since the <show-box> originally reached beyond the <html> element such that the page was extended this is still the case regardless of the fact that the element appears moved into the document.
So in order to fix the problem change
.show-text {
position: relative;
}
to
.show-text {
position: absolute;
}

Overlay Div On Top of Img at Precise Location

I have checked other posts but none mentioned about a precise location to overlay.
Consider that I have an image, for eg. a traffic light. I need to overlay (not sure if this is the correct term or not) a div on top of the precise location of, the green lamp, for example. This is so that I can animate the div via jQuery to change the colour of the div in order to have an effect that the image is being animated.
The problem now is how to be precise in this, so that the location of the div completely matches that part of the image? Does it mean having to measure the pixels before setting the top and left of the divs? Or is there a smarter way?
I have considered other options such as using canvas (or svg, or silverlight) to redraw the whole thing instead of embedding the image (i.e. redraw a whole new traffic light picture). However, for this I believe it will be way more complicated than what I asked. Correct me if I am wrong here.
Please advise.
One way is to put the image inside a div which is either positioned relative if you want it to be inline with other elements or positioned absolute if you want to set its position on the page. Then position absolutely the overlapping div inside the same div as the image.
for example
Styles
#holder {
position:relative;
}
#over {
position:absolute;
width:40px;
height:40px;
left:20px;
top:30px;
}
Body
<div id='holder'>
<img src='IMAGE SOURCE'>
<div id='over'></div>
</div>
You will need to adjust the width, height, left and top of the div with id='over' as necessary.
You could replace the div with id='over' with an image use position absolute on this image and set left and top as needed.

Rollover Image to Text with Transparent Background

I haven't worked much with Javascript, but I have a rough idea of how to make an image rollover to another image. I'm trying to make an image that, when moused over, will become a transparent background to a block of text that will occupy the space the image occupied. I've seen lots of tutorials but nothing matching quite that.
Also: is there any way to format this text with css or otherwise? (Like adding padding, line breaks, etc.)
Any help or links to a site where I can figure it out would be greatly appreciated! Thanks!
This fiddle is a pure css implementation that changes the opacity of an image placed in front of the text on hover. To do this I used put the text and image containers both within a container div and set position: absolute so that they overlap. I then change the opacity of the image by using the :hover selector. Since the text is behind the image, it can't be selected. Let me know if this what your looking for, and specify what you would like differently if it isn't :)
If you want the text to stay after the mouseover, you could use javascript to toggle a class on the rollover and add some text. E.g., put an image as the background to a div with some class (e.g., class="solid-image"). When you want to change the element, just change the class (e.g., with myElement.className="translucent-image") and then you can either have text that was previously invisible or you can add text to the div (so long as it doesn't have children) by using the textContent or innerText element. E.g.:
text = "textContent" in document ? "textContent" : "innerText";
myDomElement[text] = "My text here";
And then add an event listener for the appropriate events.

full div area onclick

This problem was not solved.. it was just evaded.. so dont use this as reference
what i have is
<div>
<img onclick='this.style.display="none";this.parentNode.getElementsByTagName("div")[0].style.display="block";this.parentNode.getElementsByTagName("div")[0].style.width=this.offsetWidth+"px";this.parentNode.getElementsByTagName("div")[0].style.height=this.height+"px";' src='http://static.***.pl/cache/***.pl/math/cafc682a15c9c6f1b7bb41eb004d6c45935cbf06434221f7201665f85242cb94.png'/>
<div onclick='this.style.display="none";this.parentNode.getElementsByTagName("img")[0].style.display="inline";' style='display:none'>
<pre style='width:100%;height:100%;'>
\lim_{t\to\infty}\int\limits_1^{t} \frac{1}{x^2}\,dx=\lim_{t\to\infty}\left(-\frac{1}{x}\right)\bigg|_1^t=\lim_{t\to\infty}\left(-\frac{1}{t}-\left(-\frac{1}{1}\right)\right)=\kappa=1880154404
</pre>
</div>
</div>
yes i know its ugly but well..
my problem is when i click the image it does what i want but if i then click the div it only works if i click on the text and i want it to work for the full div !
i dont want to use document.getElementById etc...
there will be multiple instances of this code and it will be in unknown places.
i really dont want to write up bloated code to do this (this includes jQuery,flash,.NET, Zend Engine etc etc...)
my question is simple :
why the hell does it work only if i click on text and how to fire onclick for the whole div
In your original Javascript action, you were setting the width and height of your div to zero, which means that there is no area to click on.
Here is a demo: http://jsfiddle.net/audetwebdesign/ndKqM/
which should demonstrate the fix. I added some background color and padding to show the dimensions of the various boxes.
I removed the parts of the JS that calculated width and height and that fixed the issue.
If you click on the lime green area that holds your text, the action works.
Unless there is some other reason, you don't need to adjust width or height.
It's hard to tell what behavior you really want.
You are setting the image to display:none, and then you set the style.height and style.width of the sibling div to image.height and image.width. So - those will both be zero (as display:none is set for the image).
Do yourself a favor and set background colors or borders for your divs so you can see what's going on as you code.
Use an A tag with your onclick event and a null URL href="javascript://" instead of a DIV

Find specific text in a DIV according to offset in pixels

I want to insert an image tag into a block of text so that the image is, say, 100 pixels down in the DIV.
<div>
A lot of text in a text block and a <img tag> somewhere
that is floated left or right and positioned inside the text block
</div>
So, the tag above is put in the text block to be floated so that it is positioned at 100px DOWN in the DIV. Now, this can't be done statically, it has to be done in javascript since 100px down in the div may be represented by different text depending on font rendering issues and such.
So, is there a way to find what "word" in a text block that is 100px down in the DIV? jQuery perhaps?
The short answer is no
Basically it comes down to the DOM doesn't give a way for you to get an elements pixel position. There are sort of hacks you can do for some browsers, but good luck getting a solution working.
If you cannot get the position of the containing div, you are not going to get the position for the text within.
Leaving aside the no, if you were to find a way to get the div's pixel height, I would follow a procedure similar to the following.
Get the text from inside the div and store it in a local var.
Inside a loop for each word in the text:
Insert a div tag into just before the word.
Get the pixel position of the div tag.
Use this to determine the closest word to pixel pos 100 down.
Once you have the closest position, create a document fragment to build up your new inner for the div
Replace the div's content with the document fragment.

Categories

Resources