Reputation: 11275
I have a line of text as follow:
->A B C D E F G H I J <-
I want to position the line of text using CSS
such that letter D is at the centre of the page as shown below:
-> A B C D E F G H I J <-
Any idea?
Upvotes: 0
Views: 886
Reputation: 253396
This is posted for two simple reasons:
That said, here's a plain JavaScript solution that does not require any library. It's somewhat cumbersome, and I feel that there must be ways in which it can be simplified, however:
// helper function, to save typing later on.
function gEBTN(tag, parent, index) {
if (!parent && !index) {
return document.getElementsByTagName(tag);
}
else if (parent && !index) {
return parent.getElementsByTagName(tag);
}
else if (index) {
return parent.getElementsByTagName(tag)[index];
}
}
// helper function, to save typing later on.
function gCS(elem, parent, prop) {
if (!prop && parent) {
return window.getComputedStyle(elem.parentNode, null).getPropertyValue('width');
}
else if (prop && parent == true) {
return window.getComputedStyle(elem.parentNode, null).getPropertyValue(prop);
}
else if (!parent && !prop) {
return window.getComputedStyle(elem, null).getPropertyValue('width');
}
else {
return window.getComputedStyle(elem, null).getPropertyValue(prop);
}
}
// page: number.
// navElemId: a quoted string, the Id of the element containing
// the navigation elements, defaults to 'navigation'
// container: a quoted string, the type of element ('div','span','li'...)
// that forms the navigation 'buttons.' Defaults to 'li.'
function centreNavigationOn(page, navElemId, container) {
if (!page) { // at minimum you have to supply the page you want to centre on
return false;
}
else {
var navElemId = navElemId || 'navigation';
var navElem = document.getElementById(navElemId);
var containers = gEBTN(container) || gEBTN('li', navElem);
for (var i = 0, len = containers.length; i < len; i++) {
if (containers[i].innerHTML == page) {
var centreOn = containers[i];
}
else {
// just for an easy visual difference between the centred/current
// page and the others. Adjust/remove according to taste
containers[i].style.opacity = '0.3';
}
}
if (!centreOn){
// if no page is found to be centred on, quits
console.log('No element found to centre on. Quitting now.');
return false;
}
// again, just for simple visual difference between current and others...
centreOn.style.backgroundColor = '#f90';
centreOn.style.opacity = '1';
// finds the width of the centreOn element
var cOnWidth = parseInt(gCS(centreOn),10);
var cOnLeftOffset = centreOn.offsetLeft;
// the centreOn element's parent's parent's width
// this made sense when I wrote it, now...I'm not so sure... =/
cPPWidth = parseInt(gCS(centreOn.parentNode.parentNode),10);
// works out by what distance the centreOn element's parent
// must be moved in order to centre the centreOn element within the page.
var moveBy = Math.round((cPPWidth/2) - (cOnLeftOffset + (cOnWidth/2)));
centreOn.parentNode.style.marginLeft = moveBy + 'px';
}
};
centreNavigationOn(4, 'navigation', 'li');
Notes: this function will fail in those browsers, such as IE, that have no implementation of window.getComputedStyle()
. This probably guarantees that, as interesting as it was to put together, this script is unlikely to be used. Except, perhaps, in a modified form (I do, of course, freely give this script to anyone who wants to use it, releasing it even beyond the CC-By-SA license of Stack Overflow, as I think I'm able...). Though if anyone does modify it, I'd genuinely appreciate their linking to the modified version, either in comments or by editing this answer to add links...
References:
element.innerHTML
.element.offsetLeft
.element.style
.document.getElementById()
.document.getElementsByTagName()
.Math.round()
.node.parentNode
.parseInt()
.window.getComputedStyle()
.Upvotes: 1
Reputation: 105905
If you use a monospaced font then you can use position:relative;
and move your row of text, since every letter and space has the same size (demo). You can achieve a similar result on fonts without fixed-width, but the offset (
left:;
) is a little bit harder to calculate, as almost every letter occupies another amount of horizontal space.
<nav class="letter monospace">
<div>A B C D E F G H I J</div> <!-- monospaced font demo -->
</nav>
<nav class="letter">
<div>A B C D E F G H I J</div> <!-- standard browser font demo -->
</nav>
<div id="leftmiddle"> </div>
<div id="rightmiddle"> </div>
nav.letter{
font-size:2em;
text-align:center;
}
nav.letter > div{ /* standard browser font */
position:relative;
left:1.05em; /* you have to calculate the horizontal shift yourself based on the font you're using */
}
nav.letter.monospace{
font-family:monospace;
}
nav.letter.monospace > div{ /* monospaced font */
position:relative;
left:1.75em; /* to center the row around 'E' change to 0.75em, for C to 2.75em... */
}
nav ~ div{
width:49%;
min-height:200px;
height: 80%;
}
#leftmiddle{ float:left; border-right:1px solid;}
#rightmiddle{ float:right; border-left:1px solid;}
HTML4 demo, working in IE7-9, FF10, Opera, Chrome.
UPDATE: See this alternative demo (working in IE7-9, FF10, Opera, Chrome):
<div class="letter">
<div class="wrapper">
<div class="before">
A B C
</div>
D
<div class="after">
E F G H I J
</div>
</div>
</div>
.letter{
text-align:center;
overflow:hidden;
}
.letter > .wrapper{
width:1em;
margin:auto;
position:relative;
}
.letter > .wrapper > .before{
position:absolute;
right:125%;
text-align:right;
width:10em;
}
.letter > .wrapper > .after{
position:absolute;
text-align:left;
top:0;
left:125%;
width:20em;
}
Upvotes: 3
Reputation: 17573
As @DavidThomas pointed out, JavaScript is required. I just wanted to expand on this a bit.
CSS cannot achieve this for a couple main reasons:
D
is centered until the document flow has been established. But the application of CSS is central to document flow, so at the time that CSS is being applied it can't possibly know what the final, resulting document will be. In other words, we'd have a catch 22 on our hands if CSS could be used for this. In order to "know" how to position that line of text, the page's CSS would already need to know what the final document would look like. But in order to get the final document, the CSS first needs to be applied.In contrast, JavaScript can be used to solve this issue because:
Hard to say how complicated it would be to achieve with JavaScript without knowing more about your specific case. If you know JavaScript, however, I think it would be fairly simple.
Upvotes: 1
Reputation: 720
Maybe use something like
<div id="container" style="position: absolute; width:1000px; height:10px">
<div id="innerContainer" style="position: absolute">
<span>A</span><span>B</span><span>C</span><span>D</span><span>E</span><span>F</span>
</div>
</div>
and then something like the following in JQuery in $(document).ready() {}
var left_pad = 20; // set this to container width / 2
// calculate it or hard code it
$("#innerContainer").css("left"),$((left_pad - span:contains('D').position().left) + 'px')
just off the top of my head, no time to test, but hope it points you in the right direction. With a bit of patience this should be able to be gotten working.
Upvotes: 1