[HTML]
What is the simplest solution (least amount of code) to align words when using non-monospace font ?
I need to achieve this:
« ... Just some random text. This
is just some random text.
This is just some random
text. This is just random. »
"is" should be exactly aligned with the word "just" above
What I tried so far:
(1) would be the solution, but doesn't work for me, seems deprecated:
text text text text <tab id=t1>target text<br>
<tab to=t1>Should be aligned with target.
(Adding quotes to "t1" in both lines doesn't make it work either.)
(2) negative indent for first line:
text-indent: -3em;
This works, but it's not an exact method, as I have to visually adjust the em number to make the alignment match. Plus: depending on the user's font and size, etc. the alignment won't necessarily match for the user.
Not finding a solution to simple problems drives me crazy :(
You can do this with dirty ::before hacks:
span.aligned {
font-family: sans-serif;
display: block;
white-space: pre;
position: relative;
margin-left: 30px;
}
span.aligned::before {
content: "« ...";
position: absolute;
left: -30px;
}
span.aligned::after {
content: " »";
}
<span class="aligned">Just some random text. This
is just some random text.
This is just some random
text. This is just random.</span>
It requires you to hard-code the space you want between the < ... and the content, but it's pretty flexible beyond that small detail.
Like this: http://codepen.io/anon/pen/GZLMjG
Use two DIVs, float them both left, with width: auto;. Put the text that's supposed to be on the left side into the first DIV, the rest into the second one. Use <br> tags to get the line breaks in the second DIV.
(The surrounding DIV in my codepen wouldn't be necessary, that's only to make it look nicer.)
P.S.: I put a at the end of the first text part to keep the space after that word.
You can put whole aligned text in inline-block element and give it vertical-align:text-top;.
span.pre {
display: inline-block;
vertical-align: text-top;
}
<p>« ... just <span class="pre">some random text. This<br>
is just some random text.<br>
This is just some random<br>
text. This is just random. »</span>
</p>
EDIT: In Firefox vertical-align:top; seems to be working for me.
span.pre {
display: inline-block;
vertical-align: top;
}
<p>« ... just <span class="pre">some random text. This<br>
is just some random text.<br>
This is just some random<br>
text. This is just random. »</span>
</p>
This two values are defined differently, but I have no explanation why Chrome renders them in the same way and Firefox not:
top:
Align the top of the element and its descendants with the top of
the entire line.
text-top: Aligns the top of the element with the top of the parent
element's font.
The flexible and easiest way is using before pseudo but if you need to make it dynamically you can accomplish that with a little JS code, style your paragraph with position relative and put your before text in span inside it and give it position absolute, then give it's left position based on it's width, so if span width = 50 then left position would be -50 and some px to make space between it and the paragraph https://jsfiddle.net/qhdxedxo/
$(document).ready(function () {
var cont = $('.cont');
var contWidth = $('.cont').width();
var before = $('.before');
var beforeWidth = before.width();
var paragraph = cont.find('p');
cont.css({
paddingLeft: beforeWidth
});
before.css({
left: - beforeWidth - 5
});
});
.cont {
padding-left: 50px;
padding-top: 20px;
width: 300px;
height: 400px;
background-color: #eee;
}
p {
display: block;
position: relative;
background-color: #eee;
width: 80%;
float: right
}
.before {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="cont">
<p>
<span class="before">« ...</span>
Just some random text. This
is just some random text.
This is just some random
text. This is just random
is just some random
text. This is just random. »</p>
</div>
Related
NOTE: I want a CSS-only, no JavaScript solution, please. If that's not possible with CSS, then I need to avoid layout shift.
Consider this HTML content:
<div class="container">
<div class="breadcrumb">Lorem ipsum</div>
<div class="header">Bla bla bla bla bla</div>
</div>
with this initial tentative CSS:
.container {
width: 360px;
border: 1px solid red;
}
.header {
font-weight: bold;
text-align: center;
}
This looks like this:
Imagine the div.breadcrumb is a breadcrumb and the div.header is, well, a header. The former is left-aligned and the latter is centered.
What I need
Now I want to change the CSS (and the HTML if needed) so that, if the two texts are short enough that there is no horizontal overlap, the two divs "collapse" into one, or in other words, the lower div moves up as if the first didn't exist.
But if one of the texts is too long, so that the two texts horizontally overlap, then the collapse should not happen and everything would stay as initially shown.
The example above would become like this:
but if either of the texts were too long then it should look like this:
(i.e. just like the original)
What I tried
So, my first attempt would be to add this to the CSS (in addition to the above):
.breadcrumb {
float: left;
}
But this has two issues:
As long as the two texts are short enough, it almost does the trick, but the header is centered within the space that remains to the right of the breadcrumbs, not centered to the total width.
When there is not enough space for both texts on one line, the header starts getting wrapped instead of going as a whole to a new line:
Even accepting issue 1, I tried to fix issue 2 with this:
.breadcrumb {
float: left;
}
.header {
white-space: nowrap;
}
I would expect this to fail when the header text itself is longer than what fits in one line (which would definitely be a problem, because I do have longer-than-one-line titles), but it fails even earlier:
I would expect it to go into a new line in this case, but either way, that wouldn't be a complete solution anyway.
So, how do I do it?
Is it even possible in pure CSS?
I altered some of the HTML and CSS to get the desired result.
As you will see, that header is not centered, so I added some extra container to center it in its spanning area. You can change that according to needs.
If you want to center the header exactly than you can play around the position: absolute property and change it to position: relative when flex-flow: column is activated.
flex-flow will be very useful in your case. So when it exceeds a certain word limit you can change the flow from row(default) to column.
function contentWidth() {
var container = document.getElementsByClassName("container");
var containerText = document.getElementsByClassName("containerText");
let lengths = Array.from(containerText).map(e => e.innerHTML.length);
// Lengths take the length of the letters in the
// container text using the mapping function
let max = Math.max(...lengths);
// Now we will calculate the maximum value from both of
// the text. This is done so that if any of them
// exceeds word limit than they get spanned in
// new lines (sort of)
if (max > 20) { // You can define any letter limit to make both span in new lines
container[0].style.flexFlow = "column"
}
}
contentWidth();
.container {
width: 360px;
border: 1px solid red;
display: flex;
}
.header {
font-weight: bold;
text-align: center;
display: block
}
.reed {
display: flex;
width: 100%;
justify-content: center;
}
.breadcrumb {
flex-shrink: 0
}
<div class="container">
<div class="breadcrumb containerText">Lorem ipsumsd</div>
<div class="reed">
<div class="header containerText">Bla bla bla bla bla</div>
</div>
</div>
with this initial tentative CSS:
<div class="demo"></div>
I am trying to make a simple
label: value
pairing look nice. The problem I have is that when the value is so long that it wraps around and goes on to a second line, the second line starts below the label text. I would like it to start on the same horizontal position as the first line of text.
The HTML looks like this:
<div class="status-container">
<span class="status-label">Status:</span>
<span class="status-text">This is some rather long text that I would like to the second line of text to start at the same horizontal position as the first line. At the moment it wraps beneath the 'status:' label which is annoying</span>
</div>
The CSS looks like this:
.status-container {
margin-top: 100px;
}
.status-text {
font-weight: bold;
margin-left: 10px;
}
I have create a PLNKR to show how it looks: https://plnkr.co/edit/qbFj4bwEpPf7aUldvjBU
I am sure I am forgetting something extremely simple and obvious, but it is a while since I did this CSS stuff..... All help much appreciated.
And don't forget the overflow:hidden trick:
.status-label {
float:left; padding-right:10px;
}
.status-text {
overflow:hidden; display:block;
}
<div class="status-container">
<span class="status-label">Status:</span>
<span class="status-text">This is some rather long text that I would like to the second line of text to start at the same horizontal position as the first line. At the moment it wraps beneath the 'status:' label which is annoying</span>
</div>
Probably one of the best/quickest ways with the best browser support is to use display:table:
.status-container {
margin-top: 100px;
display: table;
}
.status-text {
font-weight: bold;
padding-left: 10px;
display: table-cell;
}
.status-label {
display: table-cell;
}
<div class="status-container">
<span class="status-label">Status:</span>
<span class="status-text">This is some rather long text that I would like to the second line of text to start at the same horizontal position as the first line. At the moment it wraps beneath the 'status:' label which is annoying</span>
</div>
Otherwise, if you don't need IE9 support, use a flexbox layout:
.status-container {
margin-top: 100px;
display: flex;
}
.status-text {
font-weight: bold;
padding-left: 10px;
}
<div class="status-container">
<span class="status-label">Status:</span>
<span class="status-text">This is some rather long text that I would like to the second line of text to start at the same horizontal position as the first line. At the moment it wraps beneath the 'status:' label which is annoying</span>
</div>
You can always display them table-like
.status-label{
display:table-cell;
}
.status-text{
display: table-cell;
padding-left:10px;
}
Use inline block in your css classes to make them line up horizontally.
.status-label, .status-text {
display: inline-block;
}
I have a div with content like this:
<div class="myDiv">
Here's some text that vary in length <span class="separator">/</span> Some other text <_other elements etc>
</div>
What I want is, only using CSS, to display the first text and hide the rest.
I have tried .myDiv *:not(:first-child) { display: none; } which hides all elements, except the first separator. All texts are still visible.
Is this even possible, only using CSS?
Edit: the text is in variable lenght, but this variation is restricted between 14 and 21 chars. It will never be line breaked. (Added this info for solutions like set the div to a width and visibility:hidden or solutions like that which is fully acceptable)
This is how I would do it:
<div class="myDiv"><span>Here's some text that vary in length</span> <span class="separator">/<span><span> Some other text </span><span><_other elements etc></span>
</div>
.myDiv > span:not(:first-child) {
display:none;
}
Here is the JSFiddle demo
Separate your text using span properly and then apply the css to hide the spans if its not the first-child
It is not possible to directly select text nodes using CSS so the logical way of achieving this would be to wrap the text in an element and hide that. Unfortunately, this is not an option in this instance as the HTML markup cannot be modified and JavaScript cannot be used.
Luckily, we can rely on two things:
The text will always be on one line
The .separator element will exist
We can therefore use a combination of overflow on .myDiv and a pseudo element in .separator to forcibly hide the unwanted text:
Add height: 1em; and line-height: 1em; to .myDiv to force it only to show one line of text
Add overflow: hidden; to .mDiv to ensure that the overflown content is hidden
Create an :after pseudo element in .separator and set it to display: block; to ensure that it is forced onto a new line. This will ensure that the separator itself (/) is still shown
.myDiv {
height: 1em;
line-height: 1em;
overflow: hidden;
}
.separator:after {
content:"";
display: block;
}
<div class="myDiv">Here's some text that vary in length <span class="separator">/</span> Some other text
<_other elements etc>
</div>
If the separator is not required the CSS can be simplified. The pseudo element can be removed and .separator itself can be set to display: block; to force it onto a new line.
.myDiv {
height: 1em;
line-height: 1em;
overflow: hidden;
}
.separator {
display: block;
}
<div class="myDiv">Here's some text that vary in length <span class="separator">/</span> Some other text
<_other elements etc>
</div>
Edited You can Use this also
.myDiv{
max-width: 28.5ch;
overflow: hidden;
white-space: nowrap;
}
OR
<style>
.myDiv *:first-child
{
display:none;
}
</style>
<div class="myDiv">Here's some text that vary in length <span class="separator"> Some other text <_other elements etc></span>
I'm not the best at HTML. Essentially I am trying to get the effect of a lot of line breaks, without filling my code with a lot of consecutive <br> tags. What I have in my head is this CSS:
.movedown {
position: relative;
down: 120px;
}
and this HTML, where my text is:
<span class="movedown">*text here*</span>
I only need it on a single page. Anyone know where I'm going wrong?
Assuming you want to inject lots of breaks between two words you can inject a span tag styled as follows:
.long-br {
display: block;
height: 12em; /* 12em is roughly 10 lines at current font size/1.2 line height */
}
<p>Hello <span class="long-br"></span> World</p>
Alternate: if you want to insert lots of breaks between two blocks of text, the ideal way is to use margins:
.long-gap {
margin-top: 12em;
}
<p>Paragraph 1</p>
<p class="long-gap">Paragraph 2</p>
Try this:
.movedown {
position: relative; //Not required
margin-top: 120px;
}
You need to use the CSS property margin-top to add some space without using line breaks.
.movedown {
margin-top: 120px;
}
down is not an existing css rule. What you should be using is a div with margin-top, this creates a space above the element.
.down {
margin-top: 50px;
}
*top text*
<div class="down">*text here*</div>
Instead of 'down' try:
top:120px;
Just use <div> elements instead of <span>.
By default div is a block style element and span is inline.
block occupies the whole row, so each new one will be on a new row.
You can change the default behaviour with CSS but better to get a grip of the basic elements first.
My question is simple: what happens to inline-block elements inside of absolutely positioned elements? I have a little example to illustrate what I mean. It's hard to explain otherwise. The question is why the .icon inside of the .tag is not positioned like the previous .icon (that is, inline and to the right of the text)
The code below can be viewed # http://jsbin.com/itole4/5
<html>
<head>
<style>
.field { position: relative; border: 2px solid black;}
.tag { position: absolute; left: 100%; top: -2px; background: black; color: white;}
.icon { width:16px;height:16px; display: inline-block; background: gray; text-indent: -999px;}
</style>
</head>
<body>
<a>Some text <span class='icon'>X</span> </a>
<h2>
<span class='field'>Some Text<span class='tag'> tag<span class='icon'>x</span></span></span>
</h2>
<h2>
<span class='field'>Some Text</span>
</h2>
</body>
</html>
Actually, the icon is acting exactly the same. To test, try setting a's style to
display: inline-block; width: 50px;
When you make a tag position: absolute, it causes the tag to no longer have an automatic width of 100% of its parent, but rather to have the minimal width it can take according to heuristics within the browser (browser-dependent). The inline block acts like "inline", like an image, and is thus wrapped to the next line at the first chance (which is right after the word "tag").
So the short answer is: the icon is acting the same, but the block containing it is not.
In order to force the icon on the same line, as on the first line, you can add white-space: pre;. See: http://jsbin.com/itole4/6 (also see comment below)
because the .field has position relative and if you will add the .icon with style : position:absolute;top:0px; inside of the .field the .icon will be added on '0px' on top of the .field not of body
I can't explain it better in English >.<, i hope you can understand
it's not the positioning - it's the element containing the "icon" class..in one you've got a plain inline a the other a nested setup where the parent is an block level h2 this means your "inline-bock" has different line-heights and vertical alignment