when it comes to wrap point how can we add animation?
maybe this can help:
we have a header and inside of that header we have container with flex attr and the direction is column when we resize our browser from bottom to top or when we changing height of browser those items suddenly reshape , I just want to add animation to this event.thx
<header>
<div class="container">
<div class="item1 item"></div>
<div class="item2 item"></div>
<div class="item3 item"></div></div></header>
header {
width: 200vw;
max-height: 100vh ;
}
.container{
display: flex;
max-height:100vh;
flex-direction: column;
flex-wrap: wrap;
align-content:flex-start;
}
.item1 {
background-color: red;
height: 200px;
flex: 1 0 150px;
}
.item2 {
background-color: blue;
height: 200px;
flex: 1 0 150px;
}
.item3 {
background-color: orange;
height: 200px;
flex: 1 0 150px;
}
I had a similar need and created a simple utility to achieve it.
- Demo at CodePen: https://codepen.io/hideya/pen/Jamabx
- GH gist: https://gist.github.com/hideya/16ed168a42f74eb5d2162b4e743940ff
The implementation is a bit wild and pretty much assumes no change in flex items except xy coords. You may need to adjust z-index, as it switches item's 'position' to 'absolute'.
Hope this helps.
window.addEventListener('load', function(event) {
var targetClassName = 'flex-wrap-anim';
var defaultDuration = '0.3s';
var dummyList = [];
function addDummy(item, duration) {
var top = item.offsetTop;
var left = item.offsetLeft;
setTimeout(function() {
item.style.position = 'absolute';
item.style.top = top + 'px';
item.style.left = left + 'px';
var dummyDiv = document.createElement('div');
dummyDiv.classList.add(targetClassName + '-dummy');
var rect = item.getBoundingClientRect();
dummyDiv.style.width = rect.width + 'px';
dummyDiv.style.height = rect.height + 'px';
dummyDiv.style.visibility = 'hidden';
dummyDiv['__' + targetClassName + '_pair'] = item;
dummyDiv['__' + targetClassName + '_duration'] = duration;
item.parentNode.appendChild(dummyDiv);
dummyList.push(dummyDiv);
}, 0);
}
var conts = document.getElementsByClassName(targetClassName);
for (var i = 0, max = conts.length; i < max; i++) {
var cont = conts[i];
cont.style.positoin = 'relative';
var duration = cont.getAttribute('data-duration')
|| defaultDuration;
var items = cont.getElementsByTagName('div');
for (var i = 0, max = items.length; i < max; i++) {
addDummy(items[i], duration);
}
}
window.addEventListener('resize', function(event) {
dummyList.forEach(function(dummyDiv) {
var item = dummyDiv['__' + targetClassName + '_pair'];
var duration = dummyDiv['__' + targetClassName + '_duration'];
if (item.offsetTop != dummyDiv.offsetTop) {
item.style.transition = 'all ' + duration;
item.style.top = dummyDiv.offsetTop + 'px';
item.style.left = dummyDiv.offsetLeft + 'px';
} else {
item.style.transition = '';
item.style.left = dummyDiv.offsetLeft + 'px';
}
});
});
});
While this cannot be done with CSS alone, you can accomplish this using JQuery. When looking at a flexbox using rows, the flexbox will change height if a new row is created or removed. Knowing this, we can add a .resize() function to the page to test if a window resize has altered the height of the flexbox. If it has, you can then execute an animation. I have created an example JFiddle here.
Here is the code that makes this work:
$(document).ready(function() {
var height = $('.container').css('height');
var id;
$(window).resize(function() {
clearTimeout(id);
id = setTimeout(doneResizing, 500);
});
function doneResizing() {
var newheight = $('.container').css('height');
if (newheight != height) {
$('.item').fadeOut();
$('.item').fadeIn();
height = newheight;
}
}
});
Now with a flexbox using columns, we need to detect when a change in width occurs. This is slightly more difficult as the flexbox width will take up the maximum allotted width as it is a block style element by default. So to accomplish this, you either need to set it as an inline flexbox using display: inline-flex, or set a maximum width for the flexbox equal to the width of its contents at its largest. Once you have set one of those, you can use the same code as above, except tweaking it to detect changes in width as opposed to height.
These changes applied an animation to all elements on resize. What if you want to only apply it to the element whose row/column changes? This would take more effort but is do-able. You would need to write many if-statements in your javascript/jquery code to catch which flex-item to apply the animation to based on width/height.
Related
I have some javascript which will change the col-span-{x} class of a div to correctly give the element its width on the page. I would like this change to be animated over a second instead of an instant jump.
<div class="card col-span-{colSpan} transition duration-1000">...</div>
As per the Tailwind docs, col-span-{number} classes are setting the grid-column CSS property (MDN), namely class names col-span-1 and col-span-2 correspond to grid-column: span 1 / span 1; and grid-column: span 2 / span 2;.
These grid-column shorthand property and its values are not animatable. So, you have to fight the headwind of animating the widths yourself, in a tedious way like this:
clone the animated grid cell element and its next neighbour
add transition: width 1s; to the style of clones
put the clones exactly over their originals using element.getBoundingClientRect() for their pixel position and dimensions
change the col-span-{number} class names in the origin elements as needed
get the pixel position and dimensions of the originals with new col-span-{number} classes
feed new widths to the clone elements
on the transitionend event, remove the clones and show the originals
Deal with the literal edge-cases when you change the col-span-{number} on an edgemost item.
Well, here's a demo that needs refactoring and resembles the good old Masonry layout.
let grid;
const hide = (elem) => {
elem.style.opacity = 0;
}
const show = (elem) => {
elem.style.opacity = 1;
}
const animateWidth = (elem) => {
const gridRect = grid.getBoundingClientRect();
const targetRect = elem.getBoundingClientRect();
const clone = elem.cloneNode();
clone.style.pointerEvents = 'none';
clone.innerHTML = elem.innerHTML + ' clone';
clone.classList.add('clone');
clone.style.position = 'absolute';
clone.style.zIndex = 999;
clone.style.transition = 'width 1s, left 1s, top 1s';
const oldWidth = targetRect.width;
clone.style.width = oldWidth + 'px';
const top = targetRect.y - gridRect.y;
clone.style.top = top ? top + 'px' : 0;
const left = targetRect.x - gridRect.x;
clone.style.left = left ? left + 'px' : 0;
grid.appendChild(clone);
hide(elem);
let nextSibling;
let nextSiblingClone;
if (elem.nextSibling && !elem.nextSibling.classList.contains('clone')) {
nextSibling = elem.nextSibling;
nextSiblingClone = createAndGetNextSiblingClone(elem.nextSibling);
}
elem.classList.toggle('col-span-1');
elem.classList.toggle('col-span-2');
const newWidth = elem.getBoundingClientRect().width;
clone.style.width = newWidth ? newWidth + 'px' : 0;
const newLeft = elem.getBoundingClientRect().x - gridRect.x;
clone.style.left = newLeft ? newLeft + 'px' : 0;
const newTop = elem.getBoundingClientRect().y - gridRect.y;
clone.style.top = newTop ? newTop + 'px' : 0;
if (nextSibling) {
const nextSiblingRect = nextSibling.getBoundingClientRect();
const nextSiblingLeft = nextSiblingRect.x - gridRect.x;
nextSiblingClone.style.left = nextSiblingLeft ? nextSiblingLeft + 'px' : 0;
const nextSiblingTop = nextSiblingRect.y - gridRect.y;
nextSiblingClone.style.top = nextSiblingTop ? nextSiblingTop + 'px' : 0;
}
clone.ontransitionend = (event) => {
show(elem);
if (event && event.target && event.target.parentNode) {
event.target.parentNode.removeChild(event.target);
}
}
}
const createAndGetNextSiblingClone = (elem) => {
const gridRect = grid.getBoundingClientRect();
const targetRect = elem.getBoundingClientRect();
const clone = elem.cloneNode();
clone.innerHTML = elem.innerHTML + ' clone';
clone.classList.add('clone');
clone.style.position = 'absolute';
clone.style.zIndex = 999;
clone.style.transition = 'left 1s, top 1s';
clone.style.pointerEvents = 'none';
clone.style.width = targetRect.width ? targetRect.width + 'px' : 0;
const top = targetRect.y - gridRect.y;
clone.style.top = top ? top + 'px' : 0;
const left = targetRect.x - gridRect.x;
clone.style.left = left ? left + 'px' : 0;
grid.appendChild(clone);
hide(elem);
clone.ontransitionend = (event) => {
show(elem);
if (event && event.target && event.target.parentNode) {
event.target.parentNode.removeChild(event.target);
}
}
return clone;
}
const onGridItemClick = (event) => {
animateWidth(event.target);
}
const displayTheGrid = () => {
grid = document.getElementById('grid');
'lightgreen lightblue #dabaf9 beige #ffbbbb #f9daba #99cefa'
.split(' ')
.forEach((color, index) => {
const gridItem = document.createElement('div');
gridItem.innerHTML = index;
gridItem.style.backgroundColor = color;
grid.appendChild(gridItem);
gridItem.onclick = onGridItemClick;
});
}
window.addEventListener('DOMContentLoaded', displayTheGrid);
* {
box-sizing: border-box;
}
#grid {
display: grid;
grid-template-columns: 20fr 20fr 20fr 20fr 20fr;
grid-gap: 10px;
margin-top: 10px;
position: relative;
}
#grid > div {
border-radius: 6px;
padding: 10px;
background-color: silver;
}
.col-span-1 {
grid-column: span 1 / span 1;
}
.col-span-2 {
grid-column: span 2 / span 2;
}
<!-- https://stackoverflow.com/questions/74571960 -->
<div id="grid"></div>
I don't know if with only transition property applied you can perform an animation on col-span.
Try to use transition-all instead of transition
I am really stuck. My div contains fixed size divs, texts and images with a lot of pixel based positioning. How can I just wrap them in another div and make them scale to fit the wrapper?
This might be very similar: https://css-tricks.com/scaled-proportional-blocks-with-css-and-javascript/
Let's say that some elements have a class of .scaled-wrapper, and such elements have a single child named .scaled-content. Then we have a function applyScaling which takes a single .scaled-wrapper element, and scales its child accordingly:
let scaledWrapper = document.getElementsByClassName('scaled-wrapper')[0];
let applyScaling = scaledWrapper => {
// Get the scaled content, and reset its scaling for an instant
let scaledContent = scaledWrapper.getElementsByClassName('scaled-content')[0];
scaledContent.style.transform = 'scale(1, 1)';
let { width: cw, height: ch } = scaledContent.getBoundingClientRect();
let { width: ww, height: wh } = scaledWrapper.getBoundingClientRect();
let scaleAmtX = ww / cw;
let scaleAmtY = wh / ch;
scaledContent.style.transform = `scale(${scaleAmtX}, ${scaleAmtY})`;
};
applyScaling(scaledWrapper);
// ---- The rest of the code is just for the demonstration ui ----
let change = () => {
let w = parseInt(wInp.value);
let h = parseInt(hInp.value);
if (!isNaN(w)) scaledWrapper.style.width = `${w}px`;
if (!isNaN(h)) scaledWrapper.style.height = `${h}px`;
scaledWrapper.getElementsByClassName('scaled-content')[0].innerHTML = textInp.value;
applyScaling(scaledWrapper);
};
let wInp = document.createElement('input');
wInp.setAttribute('placeholder', 'input parent width in px');
wInp.addEventListener('input', change);
wInp.value = '200';
document.body.appendChild(wInp);
let hInp = document.createElement('input');
hInp.setAttribute('placeholder', 'input parent height in px');
hInp.addEventListener('input', change);
hInp.value = '200';
document.body.appendChild(hInp);
let textInp = document.createElement('input');
textInp.setAttribute('placeholder', 'input text content');
textInp.addEventListener('input', change);
textInp.value = 'abc';
document.body.appendChild(textInp);
.scaled-wrapper {
position: absolute;
left: 10px; top: 30px;
width: 200px; height: 200px;
outline: 1px solid red;
z-index: 1;
}
.scaled-content {
box-sizing: border-box;
display: inline-block;
transform-origin: 0 0;
background-color: #ffd0d0;
z-index: -1;
}
<div class="scaled-wrapper"><div class="scaled-content">abc</div></div>
The main idea is to take the ratio of the size between parent/child, and use that to scale the child accordingly. Note that it's important that the child's transform-origin is the top-left corner (having transform-origin: 50% 50% causes the child to be centered around the parent's top-left corner).
Also note that applyScaling needs to be called if the size of the parent ever changes (for example, if the parent is a percentage size of the window, and the window resizes).
Using #Gershom's snippet, but keeping aspect ratio
let scaledWrapper = document.getElementsByClassName('scaled-wrapper')[0];
let applyScaling = scaledWrapper => {
// Get the scaled content, and reset its scaling for an instant
let scaledContent = scaledWrapper.getElementsByClassName('scaled-content')[0];
scaledContent.style.transform = 'scale(1, 1)';
let { width: cw, height: ch } = scaledContent.getBoundingClientRect();
let { width: ww, height: wh } = scaledWrapper.getBoundingClientRect();
// let scaleAmtX = ww / cw;
// let scaleAmtY = wh / ch;
let scaleAmtX = Math.min(ww / cw, wh / ch);
let scaleAmtY = scaleAmtX;
scaledContent.style.transform = `scale(${scaleAmtX}, ${scaleAmtY})`;
};
applyScaling(scaledWrapper);
// ---- The rest of the code is just for the demonstration ui ----
let change = () => {
let w = parseInt(wInp.value);
let h = parseInt(hInp.value);
if (!isNaN(w)) scaledWrapper.style.width = `${w}px`;
if (!isNaN(h)) scaledWrapper.style.height = `${h}px`;
scaledWrapper.getElementsByClassName('scaled-content')[0].innerHTML = textInp.value;
applyScaling(scaledWrapper);
};
let wInp = document.createElement('input');
wInp.setAttribute('placeholder', 'input parent width in px');
wInp.addEventListener('input', change);
wInp.value = '100';
document.body.appendChild(wInp);
let hInp = document.createElement('input');
hInp.setAttribute('placeholder', 'input parent height in px');
hInp.addEventListener('input', change);
hInp.value = '100';
document.body.appendChild(hInp);
let textInp = document.createElement('input');
textInp.setAttribute('placeholder', 'input text content');
textInp.addEventListener('input', change);
textInp.value = 'abc';
document.body.appendChild(textInp);
.wrapper-wrapper {
box-sizing: border-box;
border: solid 2px blue;
position: relative;
}
.scaled-wrapper {
position: relative;
width: 100px; height: 100px;
outline: 1px solid red;
z-index: 1;
}
.scaled-content {
box-sizing: border-box;
display: inline-block;
transform-origin: 0 0;
background-color: #ffd0d0;
z-index: -1;
}
<div class="wrapper-wrapper">
<div class="scaled-wrapper">
<div class="scaled-content">abc</div>
</div>
</div>
For React you can do it like this:
const applyScaling = (scaledWrapper, scaledContent) => {
scaledContent.style.transform = 'scale(1, 1)';
let { width: cw, height: ch } = scaledContent.getBoundingClientRect();
let { width: ww, height: wh } = scaledWrapper.getBoundingClientRect();
let scaleAmtX = Math.min(ww / cw, wh / ch);
let scaleAmtY = scaleAmtX;
scaledContent.style.transform = `scale(${scaleAmtX}, ${scaleAmtY})`;
};
const App = ()=>{
const scaledWrapper=useRef();
const scaledContent=useRef();
useEffect(()=>{
if (scaledWrapper.current && scaledContent.current) {
applyScaling(scaledWrapper.current, scaledContent.current);
}
},[scaledWrapper.current,scaledContent.current]);
return(
<div ref={scaledWrapper}>
<div ref={scaledContent}></div>
</div>
);
}
scale() is relative to the size of the current container.
height and width are relative to the size of the parent container.
In this case, I would simply set both height and width to 100% to fill the parent DOM element. If you must use scale - try 100%. After setting height and width.
I want to ask if it is possible to make the embedded airnbnb listing responsive? I am using this code for the sharing of listing:
<div class="airbnb-embed-frame" data-id="133213" data-view="home" data-hide-price="true" style="max-width:450px;width:100%;min-height:300px;height:100%;margin:auto;"><span>View On Airbnb</span>1 BR APT + 1 LIVING RM # SKYWALK CONDO (24th)<script async="" src="https://www.airbnb.com/embeddable/airbnb_jssdk"></script></div>
The container was responsive but the content of iframe is not. It only shows horizontal and vertical scroll.
I've found a workaround, not sure how well it holds up though.
Here's a codepen.
Basically, what I've done is calculate the scale by doing client width - 10 (for some margin on the right site) divided by the embedded div's width, then used that to transform it to the fitting size and set the origin to left in order to center it.
CSS:
.room-container {
display: flex;
flex-flow: row wrap;
}
.room {
width: 450px;
height: 300px;
margin: auto;
}
#media all and (max-width: 500px) {
.room-container {
flex-direction: column;
}
.room {
transform-origin: left;
}
}
JS:
(function () {
const resize = () => {
let rooms = document.getElementsByClassName('room');
for (let room of rooms) {
let scale = (window.innerWidth - 15) / room.offsetWidth;
room.style.transform = 'scale(' + scale + ')';
}
}
window.onload = () => resize();
window.onresize = () => resize();
})();
Thanks #AesopChris. I had some problems with responsiveness on Andoid devices, so I made few changes and it worked perfectly in WordPress and Elementor Page builder.
JS in Footer:
<script>
(function () {
const resize = () => {
let rooms = document.getElementsByClassName('airbnb-embed-frame');
for (let room of rooms) {
if ( window.innerWidth < 500 ) {
let scale = (screen.width - 20) / room.offsetWidth;
room.style.transform = 'scale(' + scale + ')';
} else {
room.style.transform = 'scale(1)';
}
}
}
window.onload = () => resize();
window.onresize = () => resize();
})();
</script>
I'm not sure if "sticky" is the term for this, but is there a way to make the scrollbar from overflow:auto stay visible?
I have a rather large table that I want to be scrollable horizontally; however, the table is fairly tall as well, so when the page loads the horizontal scrollbar is not within the viewport of the browser, so it's rather hard to tell that the table is scrollable at all.
<div style = 'width:900px;overflow:auto'>
<table>
<!-- Very large table here -->
</table>
</div>
The scroll bar appears below the table, but unfortunately the table is so tall you can't see it unless you scroll down.
I'd like to have the horizontal scrollbar stay visible even if the table goes off the screen, maybe fixed to the bottom of the viewport. Ideally I'd like to do it using only CSS or a minimal amount of javascript.
Here is a script for that http://jsfiddle.net/TBnqw/2288/
$(function($){
var scrollbar = $('<div id="fixed-scrollbar"><div></div></div>').appendTo($(document.body));
scrollbar.hide().css({
overflowX:'auto',
position:'fixed',
width:'100%',
bottom:0
});
var fakecontent = scrollbar.find('div');
function top(e) {
return e.offset().top;
}
function bottom(e) {
return e.offset().top + e.height();
}
var active = $([]);
function find_active() {
scrollbar.show();
var active = $([]);
$('.fixed-scrollbar').each(function() {
if (top($(this)) < top(scrollbar) && bottom($(this)) > bottom(scrollbar)) {
fakecontent.width($(this).get(0).scrollWidth);
fakecontent.height(1);
active = $(this);
}
});
fit(active);
return active;
}
function fit(active) {
if (!active.length) return scrollbar.hide();
scrollbar.css({left: active.offset().left, width:active.width()});
fakecontent.width($(this).get(0).scrollWidth);
fakecontent.height(1);
delete lastScroll;
}
function onscroll(){
var oldactive = active;
active = find_active();
if (oldactive.not(active).length) {
oldactive.unbind('scroll', update);
}
if (active.not(oldactive).length) {
active.scroll(update);
}
update();
}
var lastScroll;
function scroll() {
if (!active.length) return;
if (scrollbar.scrollLeft() === lastScroll) return;
lastScroll = scrollbar.scrollLeft();
active.scrollLeft(lastScroll);
}
function update() {
if (!active.length) return;
if (active.scrollLeft() === lastScroll) return;
lastScroll = active.scrollLeft();
scrollbar.scrollLeft(lastScroll);
}
scrollbar.scroll(scroll);
onscroll();
$(window).scroll(onscroll);
$(window).resize(onscroll);
});
It is a quick test rather than a complete generic plugin, but is a good start, I think
Here's my take, #user2451227's is almost perfect, but didn't work with nested overflowed elements and had a number of performance issues, so I rewrote it:
$(function($){
var fixedBarTemplate = '<div class="fixed-scrollbar"><div></div></div>';
var fixedBarCSS = { display: 'none', overflowX: 'scroll', position: 'fixed', width: '100%', bottom: 0 };
$('.fixed-scrollbar-container').each(function() {
var $container = $(this);
var $bar = $(fixedBarTemplate).appendTo($container).css(fixedBarCSS);
$bar.scroll(function() {
$container.scrollLeft($bar.scrollLeft());
});
$bar.data("status", "off");
});
var fixSize = function() {
$('.fixed-scrollbar').each(function() {
var $bar = $(this);
var $container = $bar.parent();
$bar.children('div').height(1).width($container[0].scrollWidth);
$bar.width($container.width()).scrollLeft($container.scrollLeft());
});
$(window).trigger("scroll.fixedbar");
};
$(window).on("load.fixedbar resize.fixedbar", function() {
fixSize();
});
var scrollTimeout = null;
$(window).on("scroll.fixedbar", function() {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
$('.fixed-scrollbar-container').each(function() {
var $container = $(this);
var $bar = $container.children('.fixed-scrollbar');
if($bar.length && ($container[0].scrollWidth > $container.width())) {
var containerOffset = {top: $container.offset().top, bottom: $container.offset().top + $container.height() };
var windowOffset = {top: $(window).scrollTop(), bottom: $(window).scrollTop() + $(window).height() };
if((containerOffset.top > windowOffset.bottom) || (windowOffset.bottom > containerOffset.bottom)) {
if($bar.data("status") == "on") {
$bar.hide().data("status", "off");
}
} else {
if($bar.data("status") == "off") {
$bar.show().data("status", "on");
$bar.scrollLeft($container.scrollLeft());
}
}
} else {
if($bar.data("status") == "on") {
$bar.hide().data("status", "off");
}
}
});
}, 50);
});
$(window).trigger("scroll.fixedbar");
});
Usage: Add the class fixed-scrollbar-container to your horizontally overflowed element, then include this code. If the container is updated or changes in size, run $(window).trigger("resize.fixedbar"); to update the bar.
Demo: http://jsfiddle.net/8zoks7wz/1/
#Mahn - I made a small update to the following function:
$('.fixed-scrollbar-container').each(function() {
var container = jQuery(this);
if (container[0].offsetWidth < container[0].scrollWidth) {
var bar = jQuery(fixedBarTemplate).appendTo(container).css(fixedBarCSS);
bar.scroll(function() {
container.scrollLeft(bar.scrollLeft());
});
bar.data("status", "off");
}
});
The if statement looks if the container offsetWidth is smaller than the scrollWidth. Else you will also get a fixed scrollbar if the content happens to be smaller than the container. I did not like having a disfunctional scrollbar, hence this edit.
How about restricting the height of the containing div so it stays within the body? You could then have the table scroll within that div.
Working jsfiddle here: http://jsfiddle.net/fybLK/
html, body {height: 100%; margin: 0; padding: 0;}
div {
width:500px;
max-height: 100%;
overflow:auto;
background: steelblue;}
table {
width: 1000px;
height: 1000px;
color: #fff;}
Here, I've set the html and body to 100% height so that the containing div can be sized.
I have two CSS classes:
.class1 {
height: 100%;
width: 300px;
border: 1px none #B0B0B0;
position: relative;
display: inline;
left: 10px;
}
.class2 {
height: 100%;
width: 200px;
position: relative;
display: inline;
margin-left: 15px;
background-color: #00CCCC;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-style: solid;
border-right-style: solid;
border-bottom-style: solid;
border-left-style: solid;
}
Now, as you can see, they're both set to display in a line (no line breaks in between elements). Which works correctly. But for some reason, ever since I set the display to inline, the Padding, the Positioning and the Margin CSS have all just stopped working. I can add a margin-left 10inches and nothing will happen. Same with padding and positioning.
Can anyone explain how to fix this?
Also, I have the relative position set on both classes, yet when viewing the page in a browser, .class2 over laps .class1 when its supposed to be just after .class1.
Any ideas?
EDIT:
Okay, so I've done a JSFiddle, but it seems to be playing up even more there....
Looks like the Width is not working....
here it is:
http://jsfiddle.net/zYbwh/1/
You need to use
display: inline-block;
instead. margin doesn't work with display: inline elements, however with inline-block it does. You can then have an inline element with margins and explicit widths/heights.
To make this work in IE7, add these two lines:
*display: inline;
zoom: 1;
It's horrible, but it works.
I know this is quite a late answer but I wrote a jQuery plugin which support padding on inline elements (with word breaking) see this JSfiddle:
http://jsfiddle.net/RxKek/
Plugin Code:
$.fn.outerHTML = function () {
// IE, Chrome & Safari will comply with the non-standard outerHTML, all others (FF) will have a fall-back for cloning
return (!this.length) ? this : (this[0].outerHTML || (
function (el) {
var div = document.createElement('div');
div.appendChild(el.cloneNode(true));
var contents = div.innerHTML;
div = null;
return contents;
})(this[0]));
};
/*
Requirements:
1. The container must NOT have a width!
2. The element needs to be formatted like this:
<div>text</div>
in stead of this:
<div>
text
</div>
*/
$.fn.fixInlineText = function (opt) {
return this.each(function () {
//First get the container width
var maxWidth = opt.width;
//Then get the width of the inline element
//To calculate the correct width the element needs to
//be 100% visible that's why we make it absolute first.
//We also do this to the container.
$(this).css("position", "absolute");
$(this).parent().css("position", "absolute").css("width", "200%");
var width = $(this).width();
$(this).css("position", "");
$(this).parent().css("position", "").css("width", "");
//Don't do anything if it fits
if (width < maxWidth) {
return;
}
//Check how many times the container fits within the box
var times = Math.ceil(width / maxWidth);
//Function for cleaning chunks
var cleanChunk = function (chunk) {
var thisChunkLength = chunk.length - 1;
if (chunk[0] == " ") chunk = chunk.substring(1);
if (chunk[thisChunkLength] == " ") chunk = chunk.substring(0, thisChunkLength);
return chunk;
};
//Divide the text into chunks
var text = $(this).html();
var textArr = text.split(" ");
var chunkLength = Math.ceil((textArr.length - 1) / times);
var chunks = [];
var curChunk = "";
var curChunkCount = 0;
var isParsingHtml = false;
//Loop through the text array and split it into chunks
for (var i in textArr) {
//When we are parsing HTML we don't want to count the
//spaces since the user doesn't see it.
if (isParsingHtml) {
//Check for a HTML end tag
if (/<\/[a-zA-Z]*>/.test(textArr[i]) || /[a-zA-Z]*>/.test(textArr[i])) {
isParsingHtml = false;
}
} else {
//Check for a HTML begin tag
if (/<[a-zA-Z]*/.test(textArr[i])) {
isParsingHtml = true;
}
}
//Calculate chunks
if (curChunkCount == (chunkLength - 1) && !isParsingHtml) {
curChunk += textArr[i] + " ";
chunks.push(cleanChunk(curChunk));
curChunk = "";
curChunkCount = -1;
} else if ((i == (textArr.length - 1))) {
curChunk += textArr[i];
chunks.push(cleanChunk(curChunk));
break;
} else {
curChunk += textArr[i] + " ";
}
if (!isParsingHtml) {
curChunkCount++;
}
}
//Convert chunks to new elements
var el = $($(this).html("").outerHTML());
for (var x in chunks) {
var new_el = el.clone().html(chunks[x]).addClass("text-render-el");
var new_el_container = $("<div/>").addClass("text-render-container");
new_el_container.append(new_el);
$(this).before(new_el_container);
}
//Finally remove the current element
$(this).remove();
});
};
Thats the problem you get when using templates, ive programmed a site in php, but the design is killing me.
So i try'd some rocket fuel for webdesigners.
And this is the problems i keep getting every step of the way...
Inline-block does not work for me, nothing works, becouse it is not my design and i dont know the setup.
Ive tryd doing the design myself, but i am out of time, i need a design yesterday.
I suggest you take what u need from the templates and delete everything else, that will schrink your problem, and save you time.