I need to find out if the contents of a span is overflowing its parent div. It works fine in Chrome and FF, but not in IE9. I have the following HTML structure:
<div class="wrapper">
<span>Dynamic text content, which may or may not overflow the parent</span>
</div>
With the following CSS:
.wrapper {
display: inline-block;
width: 80px;
height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
In "real" browsers (i.e. not IE), it is easy to check if the span is wider than the div:
var innerSpan = $('.wrapper span');
var wrapperDiv = innerSpan.parent();
if (innerSpan.width() > wrapperDiv.width()) {
// Overflow has happened
}
But in IE9, the call to innerSpan.width() only returns the visible size, which is of course always smaller that the wrapper's size. How can I detect if the text has overflown in IE9?
NOTE: It only needs to work for IE9, not IE8, IE7 or any other version.
EDIT
I found a solution, which detects overflow but requires the span to have display: block;. See my answer below.
The height of your span is 18px as the height of text.When the text overflows the .wrapper div automatically the heigth of span increases.
var height=$('.wrapper span').css("height").replace('px','');
console.log(height);
if(parseFloat(height) > 18){
console.log("overflow occured");
}
DEMO
The element must be present in the DOM in order for the width to be calculated. If you need to calculate this before the user can see the element, try hiding it before putting it into the DOM.
Code Modified:
var innerSpan = $('.wrapper span');
var wrapperDiv = innerSpan.parent();
innerSpan.hide();
alert(innerSpan.width());
alert(wrapperDiv.width());
if (innerSpan.width() > wrapperDiv.width()) {
// Overflow has happened
}
innerSpan.show();
Demo : http://jsfiddle.net/dWzeQ/2/
Hope this will help you!
It worked when I forced the span itself to be block-level, and set the overflow and text-overflow attributes on it. Then I could use scrollWidth and offsetWidth. Here's the code:
HTML:
<div class="wrapper">
<span class="inner">Dynamic text content, which may or may not overflow the parent</span>
</div>
CSS:
.wrapper {
display: inline-block;
width: 80px;
height: 20px;
}
.inner {
display: block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
And finally, the Javascript:
var innerSpan = $('.inner');
if (innerSpan[0].scrollWidth > innerSpan[0].offsetWidth) {
console.log("Overflow!");
}
Related
I have a DIV container that has a paragraph and another inner DIV displayed in line.
Inner DIV is unknown but it's always the same and not gonna change. I can sent min-width if needed. Now based on outer DIV size I need to either cut (with three dots) or show full paragraph string. But I have to set paragraph width in css to show that three dots when outer div size is too small.
<div className="divOuter">
<p>very long string</p>
<div className="divInner">some div stuff</div>
</div>
.p {
position: relative;
float: left;
text-overflow: ellipsis;
overflow: hidden;
width: ?????; // what do I set here?????
white-space: nowrap;
}
.divInner {
display: flex;
float: right;
align-items: center;
}
|--------------------------------------|
|very long string some div stuff|
|--------------------------------------|
need to get this when outer DIV resized:
|------------------------------|
|very long st... some div stuff|
|------------------------------|
|--------------------|
|ve... some div stuff|
|--------------------|
This is what you are looking for.
You don't need to give any width to the long string p element.
There is a property of flexbox called flex. When you set this to 1, it will elongate that element to take up the remaining horizontal space in the parent.
After that, you just have to give text-overflow: ellipsis; overflow: hidden; to make the ... appear.
Run the below snippet to see it working.
.divOuter {
display: flex;
width: 100%;
}
.longString {
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.divInner {}
<div class="divOuter">
<p class="longString">very long string very long string very long string very long string very long string</p>
<p class="divInner">some div stuff</p>
</div>
div {
width: 50px;
}
span {
display: inline-block;
}
p {
max-height: calc(1em + 5px);
}
<div>
<span>a</span>
<span><p class="ellipsis">b</p></span>
</div>
It seems when ellipsis is applied to the p it calculates the width as if it were the full width of the div, rather than its width - width of a (as they are display: inline)
I can see when I inspect that it calculates the ... as if it were the full width of div. Does anyone know a workaround for this (it works for the normal cases I use it in)?
I accidentally discovered that scrollTop, and scrollLeft on an element work even when an element is overflow: hidden. Can this behaviour be relied on?
Supposedly scrollTop, and scrollLeft are supposed to be zero for elements without scrollbars, and setting them on such elements is supposed to have no effect.
Yes, even if an element has CSS overflow set to hidden,
Javascript Element.scrollTop(), Element.scrollLeft() allows you to manipulate the element's scroll position if the element contains overflowing children.
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop
Here's a quick use case:
Animate gallery using scrollLeft
var GAL = $("#gal"),
n = GAL.find(">*").length;
c = 0;
$("button").on("click", function(){
GAL.animate({ scrollLeft: (++c%n) * GAL.width() });
});
#gal {
height: 40vh;
overflow: hidden; /* !! */
white-space:nowrap;
font-size: 0;
} #gal>* {
font-size: 1rem;
display: inline-block;
vertical-align: top;
width: 100%;
height: inherit;
background: 50% / cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="gal">
<div style="background-image:url(//placehold.it/800x600/cf5);"></div>
<div style="background-image:url(//placehold.it/800x600/f0f);"></div>
<div style="background-image:url(//placehold.it/800x600/444);"></div>
</div>
<button>scrollLeft</button>
Not sure yet why Chrome does not do the following but:
Firefox will remember your gallery scroll-position on historyBack (navigating back to the page where you scrolled your gallery)
This issue is not very easy to explain so I apologize if this question seems confusing.
Basically, I have a <textarea> who's height changes based off its value. If there is any vertical overflow (which would normally produce a vertical scrollbar), I increase the height of the <textarea> to match its scrollHeight property. This seems to work just fine for the first two lines, but when more text is added, I noticed that the point at which the scrollHeight increases is different for each line of text.
Here is a fiddle that demonstrates the strange behavior: http://jsfiddle.net/2zpkf6fL/2/
Type about 5 or 6 lines of text and you will see what I'm talking about.
Can anyone shed some light on this issue? Why does the scrollHeight increase at different points for different lines of text?
Here is how i do what you are looking to do.
HTML:
<div class="textarea-container">
<textarea></textarea>
<div class="textarea-size"></div>
</div>
CSS:
.textarea-container {
position: relative;
/* you should change this*/
width: 50%;
}
textarea, .textarea-size {
min-height: 25px;
/* need to manually set font and font size */
font-family: sans-serif;
font-size: 14px;
box-sizing: border-box;
padding: 4px;
border: 1px solid;
overflow: hidden;
width: 100%;
}
textarea {
height: 100%;
position: absolute;
resize:none;
/*
"pre" or "preline" or "normal" fixes Chrome issue where
whitespace at end of lines does not trigger a line break.
However, it causes the text to exhibit the behavior seen with
"pre" that is described below.
*/
white-space: normal;
}
.textarea-size {
visibility: hidden;
/*
Pre-wrap: preserve spacing and newlines, but wrap text.
Pre: preserve spacing and newlines but don't wrap text.
"pre" does not wrap well on Firefox, even with word-wrap:break-word.
"pre" on Chrome works with word-wrap, but exhibits different behavior:
Instead of entire words being moved to the next line for wrapping,
the browser will cut words in the middle for wrapping.
"pre-line" has Firefox issues
*/
white-space: pre-wrap;
/* Required for wrapping lines in Webkit,
but not necessary in Firefox if you have white-space wrapping
(pre-wrap, normal, pre-line) already set */
word-wrap: break-word;
overflow-wrap: break-word;
}
SCRIPT:
var textContainer, textareaSize, input;
var autoSize = function () {
textareaSize.innerHTML = input.value + '\n';
};
document.addEventListener('DOMContentLoaded', function() {
textContainer = document.querySelector('.textarea-container');
textareaSize = textContainer.querySelector('.textarea-size');
input = textContainer.querySelector('textarea');
autoSize();
input.addEventListener('input', autoSize);
});
Here is jsfiddle
Need to implement functionality similar to what dotdotdot jQuery plugin does
but cannot use javascript frameworks (like jquery or ext).
Is there any easy way to add the dots to the content of div or span element if content takes more space then element should???
(similar to what css overflow: ellipsis setting does)
Can't use ellipsis beacause it doesn't work with many lines when height is limited.
Thank you :)
Why not using the CSS property text-overflow? It works great as long as you define a width in your tag.
Class in CSS:
.clipped {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
<div class="clipped" style="width: 100px;" title="This is a long text">This is a long text<div>
You can also add the text to the title attribute, so the user can see the whole text when hovering over the element.
Works for any number of lines and any width without any javascript - and is responsive. Simply set your max-height to a multiple of your line height: i.e. (22px line height) * (max 3 lines of text) = (max height 66px).
https://codepen.io/freer4/pen/prKLPy
html, body, p { margin: 0; padding: 0; font-family: sans-serif;line-height:22px;}
.ellipsis{
overflow:hidden;
margin-bottom:1em;
position:relative;
}
.ellipsis:before {
content: "\02026";
position: absolute;
bottom: 0;
right:0;
width: 1.8em;
height:22px;
margin-left: -1.8em;
padding-right: 5px;
text-align: right;
background-size: 100% 100%;
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 40%, white);
z-index:2;
}
.ellipsis::after{
content:"";
position:relative;
display:block;
float:right;
background:#FFF;
width:3em;
height:22px;
margin-top:-22px;
z-index:3;
}
/*For testing*/
.ellipsis{
max-width:500px;
text-align:justify;
}
.ellipsis-3{
max-height:66px;
}
.ellipsis-5{
max-height:110px;
}
<div class="ellipsis ellipsis-3">
<p>Here we can have a great many lines of text and it works as we expect it to. Here we can have a great many lines of text and it works as we expect it to. Here we can have a great many lines of text and it works as we expect it to. Here we can have a great many lines of text and it works as we expect it to.</p>
</div>
<div class="ellipsis ellipsis-5">
<p>The number of lines shown is easily controlled by setting the max-height of the .ellipsis element. The downsides are the requirement of a wrapping element, and that if the text is precisely as long as your number of lines, you'll get a white area covering the very trailing end of your text. You've been warned. This is just some pushing text to make the element longer. See the ellipsis? Yay.</p>
</div>
You could try:
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
This will only work if your elements are not dynamically sized. They will have to have a width set or some other mechanism to keep them from growing to allow more content.
My solution to my problem can seem a little awkward, but it works for me:)
I used a little of CSS:
word-wrap: break-word;
and Javascript:
var spans = document.getElementsByTagName("span");
for (var i in spans) {
var span = spans[i];
if (/*some condition to filter spans*/) { // just
if (navigator.appName == 'Microsoft Internet Explorer') {
span.parentNode.style.display ='inline-block';
}
if (span.parentNode.clientHeight > 50 ) {
span.innerHTML = span.innerHTML.substr(0, 26) + ' ...';
}
}
}
FOR ALL Browser:
.dotdot{ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; max-width:80px}
.dotdot:before { content: '';}
<div class="dotdot">[Button Text Goes here][1]</div>