origin
result
I want to split a string into character, and make each of the character fit the container equally, this is my work for the time being: /
The first item must attached to the left, and the last item must attached to the right.
$.fn.textjustify = function() {
return this.each(function() {
var text = $(this).text(),
containerWidth = $(this).width(),
character = '',
string = '',
singleWidth = 0,
firstItemWidth = 0,
lastItemWidth = 0,
alignWidth = 0;
if ('' !== text) {
$(this).css('position', 'relative');
textArray = text.split('');
singleWidth = Math.floor(containerWidth / textArray.length);
for (i in textArray) {
// Wrapp with div to get character width
character = ('' === $.trim(textArray[i])) ? ' ' : textArray[i];
string += '<span>' + character + '</span>';
}
$(this).html(string);
firstItemWidth = $(this).find('span:first').width();
lastItemWidth = $(this).find('span:last').width();
alignWidth = containerWidth - (firstItemWidth + lastItemWidth);
$(this).find('span').each(function(i) {
if (0 === parseInt(i)) {
// The first item
$(this).css({position: 'absolute', left: 0, top: 0});
} else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
// The last item
$(this).css({position: 'absolute', right: 0, top: 0});
} else {
// Other items
// stuck in here......
var left = (i * singleWidth) - $(this).width() + firstItemWidth;
$(this).css({position: 'absolute', left: left, top: 0});
}
});
}
});
}
stuck in the algorithm of middle items's position.
origin
result
I want to split a string into character, and make each of the character fit the container equally, this is my work for the time being: http://jsfiddle/d5fu9/
The first item must attached to the left, and the last item must attached to the right.
$.fn.textjustify = function() {
return this.each(function() {
var text = $(this).text(),
containerWidth = $(this).width(),
character = '',
string = '',
singleWidth = 0,
firstItemWidth = 0,
lastItemWidth = 0,
alignWidth = 0;
if ('' !== text) {
$(this).css('position', 'relative');
textArray = text.split('');
singleWidth = Math.floor(containerWidth / textArray.length);
for (i in textArray) {
// Wrapp with div to get character width
character = ('' === $.trim(textArray[i])) ? ' ' : textArray[i];
string += '<span>' + character + '</span>';
}
$(this).html(string);
firstItemWidth = $(this).find('span:first').width();
lastItemWidth = $(this).find('span:last').width();
alignWidth = containerWidth - (firstItemWidth + lastItemWidth);
$(this).find('span').each(function(i) {
if (0 === parseInt(i)) {
// The first item
$(this).css({position: 'absolute', left: 0, top: 0});
} else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
// The last item
$(this).css({position: 'absolute', right: 0, top: 0});
} else {
// Other items
// stuck in here......
var left = (i * singleWidth) - $(this).width() + firstItemWidth;
$(this).css({position: 'absolute', left: left, top: 0});
}
});
}
});
}
stuck in the algorithm of middle items's position.
Share Improve this question edited Dec 12, 2013 at 10:23 Chan asked Dec 12, 2013 at 9:27 ChanChan 1,9696 gold badges29 silver badges38 bronze badges 1- Posted a fix where you loop all divs with the "spread" class and then fix the chars within them. – KungWaz Commented Dec 12, 2013 at 10:23
6 Answers
Reset to default 1I think this is the simplest solution. Works great with All browsers (IE included)
- without plex (and unreliable) width detection and calculation.
- without specifying the words width/height
- without relative/absolute positioning
- using pure HTML/CSS/JS/JQ tricks.
Working Fiddle
HTML:(very simple)
<div class="Box">
<div class="Centered">
<div class="Spread">Lighting</div>
<div class="Spread">我是中文</div>
</div>
</div>
CSS:(neat and tricky)
*
{
margin: 0;
padding: 0;
}
.Box
{
width: 150px;
height: 150px;
border: 1px solid red;
margin: 6px;
}
.Box:before
{
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-left: -5px;
}
.Centered
{
display: inline-block;
vertical-align: middle;
width: 100%;
}
.Spread
{
width: 100%;
text-align: justify;
font-size: 0;
}
.Spread span
{
font-size: medium;
}
.Spread:after
{
content: '';
display: inline-block;
height: 0px;
width: 100%;
}
JS/JQ:
$.fn.SplitText = function () {
return this.each(function () {
return $(this).html('<span>' + $(this).text().split('').join(' ') + '</span>');
});
}
$(function () {
$('.Spread').SplitText();
})
Explanations: as mentioned by wared in the ments, IE7 doesn't support the use of pseudo classes. but they are not necessary for the solution. Here's a Fiddle for IE7 (and all other browsers of course).
how the vertical aligning works?
when vertical-align:middle;
is used on an inline
element, it will align the middle of this element with the other inline
elements in the same line.
that's why I'm creating an inline
element with height:100%;
, so when we align our inline
element to his middle, it will actually be the middle of the container.
how the horizontal distribution works?
taking advantage of the text-align:justify;
,
we create an empty inline
element (height:0;
) with width:100%;
, we can imagine that it takes a full line, and the rest of the text takes the second line.
using justify
makes the second line spread evenly to take the exact space as the first.
let me know if you need more explanation.
I added a fixed with for spanelements for the widest char which was W in your fiddle with 15px.
span {
width: 15px;
}
Then substracted 20px from container width which will be the free space on the sides later.
singleWidth = Math.floor((containerWidth-20) / textArray.length);
Added this extra Space to the firstitemWidth so that the other chars align correctly:
firstItemWidth = $(this).find('span:first').width() + 10;
And set the position of first and last to 10 from left and right here:
if (0 === parseInt(i)) {
// The first item
$(this).css({position: 'absolute', left: 10, top: 0});
} else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
// The last item
$(this).css({position: 'absolute', right: 10, top: 0});
Here is the updated Fiddle
I hope this will work out for you ;)
I have made a script for you if you do not mind left and right spaces. You can set the right and left margins making some little modifications.
$(document).ready(function(){
var txt = $(".container").text(); //get the text
var txt2 = "";
var len = txt.length;
$(".container").empty(); //clear the content
for(i=0; i<len; i++) //surround all characters with span
{
txt2 += "<span>" + txt.substr(i,1) + "</span>";
}
$(".container").html(txt2);
$("span").css({"width": Math.round($(".container").width())/len + "px", "display":"inline-block", "text-align":"center"});
});
Fiddle is here
Try this:
DEMO: http://jsfiddle/jc2mm/4/
JS:
$(".spread").each(function(idx, elem) {
var titleElem = $(this),
titleStr = titleElem.html(),
charWidth = Math.floor(($(".box").width() / titleStr.length) * 100) / 100;
titleElem.html("");
for(var i = 0; i < titleStr.length; i++) {
titleElem.append($("<span>", {"class" : "singleChar"}).css("width", charWidth).html(titleStr[i]));
}
});
CSS:
.box {
width: 150px;
height: 150px;
border: 1px solid red;
margin: 6px;
}
.title {
margin-top: 40px;
height: 16px;
}
.singleChar {
float: left;
text-align: center;
display: block;
min-height: 1px;
}
Try this: http://jsfiddle/d5fu9/5/
Each character is contained in a box of width singleWidth
, left
is puted counting the preceding character boxes, characters are centered.
Changes:
$(this).css({width: singleWidth,position: 'absolute', left: 0, top: 0});
and
var left = i* singleWidth + (i-1)*(textArray.length-2)/(textArray.length+1);
and in CSS:
.spread {
text-align: center;
}
Here is another version http://jsfiddle/d5fu9/6/ where leftmost and rightmost characters are attached to the border.
Modified width of a single character container:
singleWidth = Math.floor((containerWidth -firstItemWidth - lastItemWidth)/ (textArray.length-2));
and how much each inner character moves from the left:
var left = firstItemWidth+(i-1)* singleWidth ;
I've made this stuff : http://jsfiddle/wared/HDbA5/.
The idea is to use paddings to create space between chars. Tested with Chrome only. It seems to fail when the DIV has no explicit fixed width, and sometimes there is one pixel remaining, I haven't investigated. Lastly, this script does not support single characters. If you're interested in this answer, this job is for you :)
I must show some code to be able to post this answer, so, here it is :
<div><span>hello</span></div>
jQuery.fn.justify = function () {
return this.each(function () {
var el = $(this),
ct = el.parent(),
chars = el.text().split(''),
bits = (chars.length - 1) * 2,
freeSpace = ct.width() - el.width(),
bitWidth = Math.floor(freeSpace / bits),
gap = freeSpace % bits;
el.html(jQuery.map(chars, function (char, i) {
var paddings = ['0', null, '0', null];
if (!i) {
paddings[1] = (bitWidth + (gap && (--gap, 1))) + 'px';
paddings[3] = '0';
} else if (i + 1 === chars.length) {
paddings[1] = '0';
paddings[3] = (bitWidth + (gap && (--gap, 1))) + 'px';
} else {
paddings[1] = (bitWidth + (gap && (--gap, 1))) + 'px';
paddings[3] = (bitWidth + (gap && (--gap, 1))) + 'px';
}
return '<span style="padding:' + paddings.join(' ') + '">' + char + '</span>';
}).join(''));
});
};
A "bit" is a portion of the free space. It's half the space between two characters :
"abc" : 4 bits ("a..b..c").
"ab cd" : 8 bits ("a..b.. ..c..d").
The "gap" is the number of pixels remaining after splitting the free space into bits. Those pixels are assigned to each "bit" until no pixels remain. Let's say gap = 1
:
bitWidth + (gap && (--gap, 1)) // gap = gap - 1 THEN bitWidth + 1
// next bit
bitWidth + (gap && (--gap, 1)) // bitWidth + 0