Javascript: element size change handler (not css) - javascript

There is a div, which has styles:
min-width:100px
min-height:100px
When I add some text to the div(using JavaScript), it changes its size. How to get the new size?
I tried
element.offsetHeight
But it doesn't work as expected. I get size larger then I need in the first time. But after some time, if I get value of this propetry again, I get real size.
Maybe it's because there is some time between setting a text and fitting it into a div? I don't know.
<div class="parent"><div class="popup"></div></div>
<style>
* {
box-sizing:border-box;
}
.parent {
position: absolute;
z-index: 0;
}
.popup {
position: absolute;
min-width: 100px;
min-height: 100px;
padding: 20px;
border-radius: 12px;
background:#000;
color:#fff;
visibility:hidden;
}
.popup:before, .popup::before, .popup:after, .popup::after {
content:"";
width:0px;
height:0px;
display: block;
position: absolute;
}
</style>
<script>
var popup = document.getElementsByClassName('popup')[0];
popup.innerHTML = 'любой текст от 3 до NNN строк';
console.log(popup.offsetHeight);
</script>

You can get the borders of the element, top, bottom, right and left and then subtract them in order to get the width and the height. This accounts for the actual pixels on the page after it has been modified:
var width = [element].getBoundingClientRect().right - [element].getBoundingClientRect().left ;
var height = [element].getBoundingClientRect().bottom - [element].getBoundingClientRect().top ;

Change this in your script. Notice that I added more text in innerHTML.
<script>
var popup = document.getElementsByClassName('popup')[0];
console.log("Before: "+popup.offsetHeight);
popup.innerHTML = 'любой текст от 3 до NNN строк<br><br>moretext';
console.log("After: "+popup.offsetHeight);
</script>
And change in your CSS the min-height to smaller value to see the difference
min-height:10px;
output in console is:
Before: 40
After: 180
Here is an example that works (open console to see the output): https://jsfiddle.net/_jserodio/q78dLz8h/

Related

Crossfade images with jQuery

Hi I'm trying to accomplish a crossfade effect for my banner images on my homepage. I'm doing this with jQuery and the fading effect is working fine.
This is my code:
<script>
function bannerImages(){
var $active = $('.banner-test .banner_one');
var $next = ($active.next().length > 0) ? $active.next() :
$('.banner-test img:first');
$next.css('z-index',2);//move the next image up the pile
$active.fadeOut(1500,function(){//fade out the top image
$active.css('z-index',1).show().removeClass('active');//reset the z-index and unhide the image
$next.css('z-index',3).addClass('active');//make the next image the top one
});
}
$(document).ready(function(){
// run every 7s
setInterval('cycleImages()', 7000);
})
</script>
As I said this is working fine however I've got one issue. In order for this to work I need to apply position:absolute to the .banner-test img class. Now I've also got another div within the .banner-test class to display some text on top of the banner image.
The code looks like this :
<div class="banner-test">
<img class="banner_one" src="../image.jpg" alt="" />
<img src="../image2.jpg" alt=""/>
<div id="text">
<p class="text1">Sample Text</p>
</div>
</div>
And the css for the #text :
#text {
position:absolute;
bottom:35px ;
left:10px;
width:70% ;
background-color:#104E8B;
font-size:1em;
color:white;
opacity:0.95;
filter:alpha(opacity=95); /* IE transparency */
}
.text1 {
padding:13px;
margin:0px;
}
.banner-test {
display: block;
position: relative;
}
So if I apply absolute positioning to the image it messes up the layout with the text (everything is pushed to the top of the page).
Can anybody think of a workaround for this?
EDIT
https://jsfiddle.net/ztrez888/1/embedded/result/ this is the fiddle - if position absolute is applied to the .banner-test img the text disappears
You said: (everything is pushed to the top of the page)
Its because your wrapper element .banner-test doesn't have a static height set. so when you apply a absolute position to the images in it .banner-test get shrink to height of the #text .text1.
Either set a height in the css:
.banner-test {
display: block;
position: relative;
height:200px; /* <--put the height of img */
}
or calculate it with jQuery:
$(document).ready(function(){
var arr = $('.banner-test img').map(function(){ // get the heights of imgs in array
return $(this).height();
}).get(),
h = Math.max.apply(Math, arr); // find out the greatest height in it.
$('.banner-test').css('height', h); // set the height here.
// run every 7s
setInterval('cycleImages()', 7000); // then cycle the images.
});
cycleImages() is been called in the setInterval and you have bannerImages() function on the page. I am assuming you have this cycleImages() function.
Updates:
#text {
position: absolute;
bottom: 30px;
left: 10px;
width: 100px;
background-color: #104E8B;
font-size: 1em;
color: white;
opacity: 0.95;
filter: alpha(opacity=95);
/* IE transparency */
z-index: 5; /* <----change these here*/
left: 10%;
top: 0;
}
Updated fiddle

highlighting characters in text depending on position of page

I have a text on my website that scrolls horizontal through the page. I’m trying to get around 8 characters highlighted in black, while the rest is grey. But those characters are meant to vary as you scroll though, the highlighted bit should remain in place.
In case this doesn’t make any sense, if grey was an x, it should look something like this:
xxxxx xpsum dolox xxx xxxx
xxxx xxsum dolox sxx xxxx
xxx xxxum dolox six xxxx x
xx xxxxm dolox sit xxxx xx
I’m trying to get this done in jQuery, but I can’t get it to work. I also like to say that I’m not at all an expert in webdesign, so I don’t know what I’m doing. Anyway, I’ve tried two different approaches, one is to say “change colour of text when going over an underlying div”. The other approach is to change the colour of the text depending on the scrolling position, but the problem here is that it takes the scrolling position of the whole div, instead of a fixed position on the page. Both don’t work at the moment, examples are here:
jsfiddle 9p29tz2f
jsfiddle 9p29tz2f/1
If anyone has any ideas how to approach this, or needs some more clarification, please let me know. Many thanks!
Clone the text and set it as a child of the overlay box then scroll them together:
$(function(){
var $bodytext = $('#bodytext'),
$clone = $bodytext.clone();
//copy the text and append it to #black:
$clone.attr("id","clone").prependTo("#black");
//scroll #clone with #bodytext:
$bodytext.scroll(function(){
$clone.scrollLeft($bodytext.scrollLeft());
});
});
http://jsfiddle.net/9p29tz2f/2/
I've taken Teemu's solution and modified it a bit: http://jsfiddle.net/9af91wcL/2/
The important bits: The code moves a white DIV (#grey-overlay) on top of the text and makes it transparent. By adding black and white pixels, you get grey. The grey level is determined by the alpha channel (0.7 in the rgba() function).
You need to assign a height or it will look odd. I use 1.5em to make sure it doesn't overlap with the scroll bar of the #bodytext div.
Also make sure that the top/left position of both div's is the same.
In your real code, you can make the horizontal scrollbar disappear and scroll with JavaScript.
HTML
<div id="grey-overlay"></div>
<div id="bodytext">text...</div>
CSS
body {
background: #ffffff;
color: #000000;
font-family: sans-serif;
font-size: 200%;
}
#bodytext {
top: 15%;
width:200px;
height: 2em;
padding: 0;
position:absolute;
overflow-x:scroll;
overflow-y:hidden;
white-space: nowrap;
}
#grey-overlay {
background-color: rgba(255, 255, 255, 0.7);
width:40px;
height: 1.5em;
top:15%;
position:fixed;
z-index: 10;
}
You need to show the same content within #black as in #bodytext, and synchronize its position relative to #bodytext scrolling. This can be achieved by using an extra wrapper around #black. Something like this:
CSS:
#cover {
top: 15%;
height:50%;
width: 120px;
padding: 0;
position:fixed;
overflow-x: hidden;
background-color: #D8D8D8;
}
#black {
color: #000000;
width:100%;
height:100%;
top:0px;
left: 0px;
position:absolute;
white-space: nowrap;
z-index: 10;
}
#bodytext {
top: 15%;
width:100%;
height:85%;
padding: 0;
position:absolute;
overflow-x:scroll;
white-space: nowrap;
color: #D8D8D8;
}
HTML:
<div id="cover">
<div id="black"></div>
</div>
JS:
$(document).ready(function () {
var black = $('#black'),
btext = $('#bodytext');
black.text(btext.text()); // Clone the content
btext.scroll(function () {
var pos = btext.scrollLeft();
black.css('left', -pos + 'px'); // Set the position to match #bodytext
});
});
A live demo at jsFiddle.
Notice, that if you need some left margin, it has also to be "calculated in" to pos.

Center and resize content

I have a user-variable string, which can range from one word to a couple sentences (and might contain any valid Unicode character), which I'd like to display within a variable width box.
In code, I'd like HTML that looks like this w/ any other CSS or JS:
<div style="width: 100%; height: 80%" id="text">
<!--<some more divs or something>-->
{{content}}
<!--</some more divs or something>-->
</div>
{{content}} should get bigger when it can be, up to some maximum font size (variable); smaller when it's longer down to some minimum (variable) and then just get cut off after that point.
In either case, I need it to be visually centered and words longer than the box should get hyphenated.
I've tried hacking something together with a combination of flexboxes and JavaScript, but couldn't figure out how to get all the bugs worked out.
Browser support doesn't really matter aside from the latest versions of mobile/desktop Chrome/Safari/Firefox.
Alright I believe this is what you were wanting to accomplish. Code is below with descriptions in the comment blocks. In chrome you'll be using the -webkit-line-clamp property, in firefox you'll be using the fadeout method since firefox doesn't support the clamp property. You can adjust the fadeout in the css to your liking. The "..." at the cutoff point will also still be present in firefox (see the .clamp:after property in the css).
Here is the updated jsFiddle
HTML (To see the changes, just remove the text until one line is shown in the div)
<div id="textparent">
<div id="text">
{{content}} adkf kfjg; ;akdfg fbfbf egdf hajkh
kajfhdg lakjfg kafd gjkahf jahfkjadlfh alkgj akjdhg fkafg
</div>
</div>
CSS
Note: -webkit-line-clamp:3; ( this is the amount of lines you want to be shown)
#text{
width:100%;
position:relative;
height:auto;
text-overflow:ellipsis;
font-size:25px;
line-height:1.1;
display:block;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp:3;
overflow:hidden;
margin:0 auto;
box-sizing:border-box;
}
#textparent{
margin:0 auto;
width:300px;
background:#eee;
top:50px;
padding:10px;
height:auto;
text-align:center;
position:relative;
height:100px;
display:-webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;
}
/*FIREFOX will make use of the clamp class*/
.clamp:after {
background: linear-gradient(to right, rgba(255, 255, 255, 0), #eeeeee 50%) repeat scroll 0 0 rgba(0, 0, 0, 0);
bottom: 0;
content: "...";
padding: 0 5px 1px 25px;
position: absolute;
right: 0;
}
.clamp {
height: 5.6em;
line-height: 1.4em;
overflow: hidden;
position: relative;
}
Javascript/JQUERY: The main variable you might want to change or play around with is [min_font_size] and [num_line_to_show] although [num_line_to_show] is already set in the CSS.
var t = $('#text');
// get the font-size of the div
var font_size = Number(t.css('font-size').replace('px', ''));
// get the line-height of the div (Note: in Chrome this returns the actual height)
var line_height = Number(t.css('line-height').replace('px', ''));
// minimum height of #text div
//
// Note: if you were in a browser and the line-height var didn't return the full
// height as it does in chrome, you would need to do this:
// var min_h = font-size * line_height
var min_h = line_height;
// number of lines to show. basically just retrieving the "-webkit-line-clamp"
// property in the css, otherwise will default to 3, which you can change.
var num_line_to_show = Number(t.css('-webkit-line-clamp')) || 3;
// the maximum height for the #text div. (the added 5 at the end is just
// personal preference)
var max_h = line_height * num_line_to_show * font_size + 5;
// get the height of the div
var h = $('#text').height();
// set this if you want the font to be set at a minimum size
// when the text is longer than one line
var min_font_size = 20;
Note: you could also try setting the minimum font size dynamically, something like this:
// change this to make the font smaller
var shrink_rate = 3;
var min_font_size = font_size - (Math.round((h/min_h)) * shrink_rate;
Continuing:
// for detecting firefox
var is_ff = navigator.userAgent.toLowerCase().indexOf('firefox');
// if the height of the div is larger than the minimum height, meaning there
// is more than one line now, the font size of the div becomes smaller.
if (h > min_h){
t.css({'font-size' : min_font_size});
// if in Firefox browser
if(is_ff > -1){
// get the new max height of #text based on the number of lines
// with the new minimum font-size
var txt_max_h = ((line_height-font_size) / num_line_to_show) * min_font_size * num_line_to_show;
// the new height is greater than the maximum height allowed for the
// smaller font size
if (t.height() > txt_max_h){
// reset the height of #text div to a fixed height
t.height((min_font_size * num_line_to_show) + 5);
// add the clamp class and css will the rest
t.addClass('clamp');
}
}
}
// if firefox, always run this to center the #text div based on its height
if(is_ff > -1){
t.css({top: ($('#textparent').height() - t.height()) / 2});
}
Hope this helps!
just in time.
See this Fiddle.
I think I succeed to do what you want. It works with Chrome, Firefox and Safari.
HTML :
<div id="container">
<div id="text">my Text !!</div>
</div>
JS :
var maxFontSize=68; // I think we cannot have bigger than that.
var minFontSize=12;
$('#text').on({
// setting an event to resize text
resize:function(e){
// if no text => return false;
if (!$(this).html().trim()) return;
// if already running => return false;
if (this.running) return;
this.running = true;
// get max-height = height of the parent element
var h = $(this).parent().height();
// clone the text element and apply some css
var clone = $(this).clone()
.removeAttr('id')
.css({'font-size':0,
'width':$(this).width(),
'opacity':0,
'position':'fixed',
'left':-1000})
.appendTo($('body'));
// Set the max font size for the clone to fit the max height;
var fontSize = minFontSize;
do {
$(this).css('font-size', fontSize+'px');
fontSize=fontSize+1;
clone.css('font-size', fontSize+'px');
} while (h > clone.height() && maxFontSize > fontSize) ;
// Set the '...' if still bigger
//start by setting back the good size to the clone.
fontSize=fontSize-1;
clone.css('font-size', fontSize+'px');
// while max-height still bigger than clone height
if (h < clone.height() && minFontSize == fontSize) {
var content = clone.html();
// try to remove the last words, one by one.
while (h < clone.height()) {
content = content.replace(/(\s[^\s]*)$/g,'...');
clone.html(content);
}
// then replace the #text content
$(this).html(clone.html());
}
// then remove the clone
clone.remove();
this.running = false;
}
})
.trigger('resize');
There is a cross-browser (IE9+) css centered text and hyphenated for webkit, codepen:
HTML:
<div class="box">
<p>
You can also position your element only in the vertical or horizontal.
This work in IE9+. This text can be also hyphenated.
</p>
</div>
CSS:
.box {
border: #3071a9 solid 1px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
color: #222;
font-size: 26px;
font-family: arial;
height: 50%;
padding: 20px;
width: 50%;
}
.box p {
text-overflow:ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp:3;
overflow: hidden;
position: absolute;
top: 50%;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
-o-transform: translate(0, -50%);
transform: translate(0, -50%);
}
Jquery Textfill Plugin by Russ Painter can come handy.
Here is the Fiddle.
<div>
<div>
<label for="dyntext">Content:</label>
<input type="text" id="dyntext" value="Hello!"></input>
</div>
<div>
<label for="maxsize">Maximal font size in pixels?</label>
<input type="text" id="maxsize" value="0"></input>
</div>
<hr />
<div class="content">
<div class="jtextfill">
<span class="dyntextval">Hello!</span>
</div>
</div>
function update() {
var size = parseInt($('#maxsize').val(), 10);
if (!isNaN(size)) {
$('.dyntextval').html($('#dyntext').val());
$('.jtextfill').textfill({debug: true, maxFontPixels: size});
}
}
$(function () {
$('#maxsize').keyup(update);
$('#dyntext').keyup(update);
update()
});
.content .jtextfill {
width: 150px;
height: 100px;
background-color: #fff;
text-align: center;
border:1px solid #333;
padding-top:40px;
padding-bottom:40px;
}
The center part is really easy, you can do this with flexbox, display:table-cell, etc
The font-size part is tricky but it's been answered in the past here: https://stackoverflow.com/a/6112914/1877754

css/javascript: number above border

how to display a small number (left top border) above a border around an element?
basically I am looking for a way to highlight elements and identify them with a number.
UPDATE:
Basically the elements highlight on mouseover by having border property defined. on mouseout, border is transparent (disappears).
what I'd like to do is how to display a number outside of the border highlight selected?
Solution I just thought about is using a custom generated numbered image border and just use border-image dynamically
Assuming you want to insert this number dynamically for any element without having to worry about relatives and absolutes here is a solution.
Code:
<div id="box"></div>
#box{
background:red;
height:140px;
width:250px;
margin:30px;
}
.number{
background:#ccc;
display:block;
font-weight:bold;
border:1px solid #000;
font-size:10px;
}
// Create an span element that will have the number
var number = $("<span />").text("5").addClass("number");
// Set the number width and height
var numberWidth = 10;
var numberHeight = 10;
// Get the target element
var element = $("#box");
// Get width, height and position
var elementWidth = element.width();
// These two are only necesary if you want to position
// the number in a different corner (e.g bottom, right)
var elementHeight = element.height();
var elementPosition = element.offset();
// Apply css to the number element
// Position is based on the target element position
number.css({
position: "absolute",
left: elementPosition.left - numberWidth,
top: elementPosition.top - numberHeight,
width: numberWidth,
height: numberHeight
});
// Insert the number to the body
number.appendTo("body");
If the identification numbers are constant and you don't want to include them in the markup as content, you can include them as attribute values and use :before pseudo-elements:
CSS:
p { position : relative }
p:hover:before {
content : attr(title);
position : absolute;
left : 0;
top : -1em
}
HTML:
<p title="1">blah blah</p>
<p title="2">blah blah</p>
<p title="3">blah blah</p>
If the identification numbers can be generated each time the page is rendered, you can use an automatic counter instead:
CSS:
p {
position : relative;
counter-increment : idnum
}
p:hover:before {
content : counter(idnum);
position : absolute;
left : 0;
top : -1em
}
See here for more information: http://www.w3.org/TR/CSS2/generate.html
What do you mean by "highlight"? Mouseover? You can provision for such visual effects by first wrapping your element with another div which will hold your number. And example:
<style>
.container:hover .label {
visibility: visible;
}
.label {
visibility: hidden;
}
.content {
margin: 1px;
border: none;
}
.content:hover {
margin: 0px;
border: 1px solid black;
}
</style>
<div class="container">
<div class="label">
123
</div>
<div class="content">
My Element
</div>
</div>
Edited to only display border on mouse over.

How to re-size text and css background image like <img> is re-sizing in this example?

In this example <img> is re-sizing as I want
Edit: re-added http://jsfiddle.net/jitendravyas/yBkFL/
But I also want to re-size Discount tag and text. if I re-size the browser window to small size then Discount tag 20% and text "Good Product" should also re-size.
I need compatibility with IE8 and 9 and latest firefox, Chorme and iPad safari
I would like to do with CSS only but if it's not possible then use of javascript/jquery is ok. Compatibility is important.
Important part of HTML and CSS
HTML (edited)
<ul>
<li>
<span class="twenty-percent">
<span class="rotate">20%</span>
</span>
<img src="image.jpg">
<span class="description">Good Product</span>
</li>
</ul>
CSS (Edited:)
li {
float: left;
width: 18%;
padding: 0;
position: relative;
float: left;
margin: 15px;
background: yellow;
display: inline }
img { width: 100%; }
li img { display: block; }
.twenty-percent {
content: '';
background:url(http: //i.imgur.com/9cfK5.png) no-repeat;
position: absolute;
right: -15px;
top: -2px;
width: 45px;
height: 45px; }
.description {
display: block;
font-size: 120%; }
.rotate {
color: #FFFFFF;
font-size: 16px;
font-weight: bold;
padding-right: 10px;
position: absolute;
right: -5px;
text-shadow: 0 1px 1px #000000;
top: 9px; }
I don't know of a pure CSS way to do it, but with a bit of jQuery, it's possible as follows:
/* Original width of the description element */
var origWidth = $('.description').width();
/* Function to set the font size of description. Based on its current width
compared to its original width. The * 70 is a factor you can use to increase
or decrease the calculated font size. */
var setFontSize = function(){
var $desc = $('.description');
$desc.css({fontSize: $desc.width()/origWidth * 70 + "%"});
}
/* Set the font size on load and when the viewport resizes */
setFontSize();
$(window).resize(setFontSize);
Here's a demo of it.
Notes
Above assumes all .description elements are same width.
You could improve the appearance of the script by hiding the text until the font size was calculated on load. This would prevent the font size jump you see before the first call to setFontSize().
If you wanted to improve the font size ratio (rather than rely on the hardcoded * 70 factor), you could use a function on load that calculated the maximum possible space for text in your .description. Then you could use this value to determine the factor.
Updated: New version of the code that resizes the green percentage discount text and image as well.
HTML
<ul>
<li>
<!-- Green circle background has been changed to an <img>. Now it
can be scaled as the size changes. It is absolutely positioned
behind the percentage text. -->
<span class="percent">
<img src="http://i.imgur.com/9cfK5.png"/>
<span class="rotate">20%</span>
</span>
<img src="http://lorempixum.com/100/200/">
<span class="description">Good Product</span>
</li>
<!-- Remaining items -->
</ul>
CSS
/* Container that holds percent text and green circle <img> */
.percent {
content: '';
position:absolute;
right:-15px;
top:-2px;
height: 45px;
width: 45px;
/* Vertically center percent text */
line-height: 45px;
font-size: 100%;
}
/* Green circle image */
.percent img {
/* Grow/shrink as .percent size changes */
width: 100%;
height: auto;
/* Absolutely position behind percentage text */
position: absolute;
z-index: 1;
top: 0;
left: 0;
}
.rotate {
/* Positions percent text above green circle <img> */
position: relative;
z-index: 2;
/* Keeps text centered as size changes */
display: block;
text-align: center;
/* remaining rules */
}
jQuery
/* Get common element references */
var $desc = $('.description');
var $percent = $('.percent');
/* Store the original values. We'll use these to smoothly change the size */
var orig = {
description: $desc.width(),
percent: $percent.width(),
right: parseInt($percent.css('right'), 10)
};
/* Sets font sizes and changes green circle image size and position */
var setFontSize = function(){
/* Get the percent of size change */
var change = $desc.width()/orig.description;
/* Update the .description font-size */
$desc.css({
fontSize: change * 100 + "%"
});
/* Update the following .percent properties:
1. font-size
2. width: to grow/shrink green circle image
3. line-height: to keep percent text vertically centered
4. right: keeps .percent container in the same proportional position */
$percent.css({
fontSize: change * 100 + "%",
width: orig.percent * change + "px",
lineHeight: orig.percent * change + "px",
right: orig.right * change + "px"
});
}
/* Set the font size on load and when the viewport resizes */
setFontSize();
$(window).resize(setFontSize);
Demo of it in action.
You could create two css classes that describe the two sizes/versions that you want. You can use jquery to detect the browser size and add and remove the appropriate css classes to your liking.
Background images do not rescale themselves like images (<img> tags). Change the 20% logo to an <img>, then size it as you do the larger image. Fonts can be sized as percents, so try setting the font-size to 120%.
To resize text, create the block of whichit is contained within in CSS. for example: Body, Main, Footer etc. then simply use the font-size command. Like so
body {
Font-size:1.1EM;
}
For the image, simply set the dimension which the want the image to be, although I recommend making the image file smaller, since this will save memory space.

Categories

Resources