prevent :after element from wrapping to next line - css

I have this HTML:
<ul>
<li class="completed"><a href="#">I want the icon to stay on the same line as this last <strong>word</strong></li>
</ul>
I'm appending an icon using the :after pseudo element:
ul li.completed a:after {
background:transparent url(img.png) no-repeat;
content: '';
display:inline-block;
width: 24px;
height: 16px;
}
The problem: if the available width is too small, the icon wraps to the next line. I would want it to stay on the same line as the last word of the link it's appended to:
Is this doable, without adding 'nowrap' to the entire link (I want the words to wrap, just not the icon).
See jsFiddle here.

JSFiddle - http://jsfiddle.net/Bk38F/65/
Add a negative margin to the pseudo element, to compensate its width:
ul li.completed a:after {
background:transparent url(img1.png) no-repeat;
content: ' ';
display: inline-block;
width: 24px;
height: 16px;
margin-right: -24px;
}
Now, that is going to make the icon overflow the container, and the line is going to break only when the text meet the end of the line. If you need to maintain the icon inside the original container width, you can add padding to compensate again:
ul li.completed a {
display: inline-block;
padding-right: 24px;
}
IMPORTANT UPDATE:
For this method to work, there must be no white space between the text and the closing tag of the element holding the pseudo element. Even though the pseudo element's width is compensated by a negative margin, the white space will make the line break when it meets the edge of the parent element. For example, this works:
<span>text goes here</span>
and this doesn't:
<span>
text goes here
</span>

you can add the image to the last word instead. that will make it break together.
add a class to word
<strong class="test">word</strong>
and .test:after { ...
http://jsfiddle.net/52dkR/
the trick is also to make that class to be inline-block
and if you want to keep the underline see this.
http://jsfiddle.net/atcJJ/
add text-decoration:inherit;

This is a little similar to a previous answer, but I thought that I'd flesh it out and explain it fully.
As soon as you set display: inline-block, :after becomes a non-text-binding element. This is why it wraps, and why nowrap has no effect. So leave display alone.
As it's a text element by default, the content binds to previous text, as long as there's no whitespace between them. So don't add any, but make sure you have content: "", or it's the same as display: none. The only problem is height and width are controlled by the content, which in this case is collapsed. So width is 0, and height is the line height.
Resize the area with padding; left or right, it doesn't matter. Add a little margin so the icon doesn't touch the text. Keep everything as relative sizes (em, pt, etc.), and use background-size: contain, so that the icon scales with the text, like an emoji or font. Finally position the icon where you want with background-position.
ul li.completed a:after {
content: "";
background: url('icon.svg');
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
margin-left: 0.2em; /* spacing*/
padding-right: 0.75em; /* sizing */
}
I've used this for my external links (a[href*="://"]:after), and it's worked fine in Firefox, Chrome, and iOS. And since the icon remains a text element, even direct text after it binds, so any closing punctuation will wrap too.

If using an icon font: Using the "non-breaking space" unicode \00a0 along with the pseudo-element content (in this case a Font Awesome glyph).
This works without any extra mark-up or special formatting or classnames.
a[href^='http']::after {
content: '\00a0\f14c';
font-family: 'Font Awesome 5 Pro', sans-serif;
line-height: 0;
}
The line-height: 0; part keeps the lines from twitching when the last 'word + icon' wrap.
CodePen example

I was having the same issue. I didn't really like the idea of adding strong or span tags to the last word, so I tried simply adding the icon as a background image with some padding-right instead of using the :after or :before pseudo elements. Worked for me!
<ul><li class="completed">I want the icon to stay on the same line as this last word</li></ul>
ul li.completed a {
background: url(img1.png) no-repeat 100% 50%;
padding-right: 18px;
}
http://jsfiddle.net/atcJJ/36/

I was attempting this with a link button and had the most success with adding padding to the right of the element as #Hugo Silva suggested, then setting the ::after to absolute position. This was a pretty simple solution and seemed to work across modern browsers.
.button {
position: relative;
color: #F00;
font-size: 1.5rem;
padding-right: 2.25rem;
}
.button::after {
content: '>>';
display: inline-block;
padding-left: .75rem;
position: absolute;
}
Here's a JS Fiddle.

Please make sure you end the tag before
<ul><li class="completed">I want the icon to stay on the same line as this last <strong>word</strong></li></ul>
Try the below css. Instead of using "after" use "before" and float right.
ul li.completed a:before {
background:transparent url(img1.png) no-repeat;
content: '';
display:inline-block;
width: 24px;
height: 16px;
float:right;
}
Please check this:
http://jsfiddle.net/supriti/atcJJ/7/

It is possible to do it without :after.
The element with background should be display:inline.
<h1><span>I want the icon to stay on the same line as this last word</span></h1>
h1 span {
padding-right: 24px;
background: url('icon.svg') no-repeat right top;
}
http://jsfiddle.net/my97k7b1/

The problem occurs when there is whitespace at the end of the text of the element, so it considers the icon as another word. My solution is to remove the white space with javascript and put it outside the element. Also, this way we avoid that text-decoration:underline styles the white space that may be at the end of a link:
$(document).ready(function () {
$("a[href$=\".pdf\"]").each(function () {
var endspace = /\s$/;
if (endspace.test($(this).html())) {
var linktx = $(this).html().replace(/\s*$/, "");
$(this).html(linktx);
$(this).after(" ");
}
});
});
In the css I add a non-breaking space \00A0 before the icon to separate it from the text, and to scale according to the font-size. In some cases, using a narrow no-break space \202F offers a better visual effect:
a[href$=".pdf"]:after {
content: "\00A0\f1c1";
font-family: "Font Awesome 5 Pro";
}
https://jsfiddle.net/poselab/910bw7zt/8/

With my particular set up, the only working solution was to use position relative, and place my icon element in a span with a position absolute. Like so:
h2 a {
position: relative;
width: auto;
}
h2 a span {
position: absolute;
right: -30px;
bottom: 0;
}
<h2>
<a href="#">
The arrow won't drop to the next line as an orphan, even if the text is long and responsive
<span>→</span>
</a>
</h2>

I just used:
white-space: nowrap;
Worked for me!

Related

Positioning CSS :after content

I'm trying to make a circular button with a character centered inside (in this case, a right-pointing arrow for a next button). I've gotten it vertically centered by adjusting the element's line-height, but I can't find a way to move it over to the side.
I tried adding both literal and unicode (\0020) space characters and that didn't move the triangle at all. Padding and margin don't work on the :after selector, and don't have the desired effect if applied to the element itself.
Here's the 'rendered' code, according to firebug (I'm using SASS, so pasting the actual code would leave out all the mixin definitions and such).
.flowbar--nav-image__next:after {
content: "▸";
}
.flowbar--nav-image:after {
color: white;
font-size: 19px;
}
.flowbar--nav-image {
background-color: #018FD6;
background-image: -moz-linear-gradient(center top , #93E3F7, #018FD6);
border-radius: 50% 50% 50% 50%;
display: inline-block;
height: 25px;
line-height: 25px;
width: 25px;
}
And the actual HTML:
<span class="flowbar--nav-image flowbar--nav-image__next"></span>
And here's what gets rendered:
This will work:
.flowbar--nav-image__next:after {
content: "▸";
display:block;
margin-left:10px;
}
http://jsfiddle.net/qTXFJ/1/
Or, instead, you could simply adjust the text alignment, which means you don't have to figure out the pixels yourself:
.flowbar--nav-image {
text-align:center;
}
http://jsfiddle.net/qTXFJ/3/

inline-block goes under floated div

I'm trying to style my headings with display:inline-block; but i've a problem with a behavior of the property.
Jsfiddle : http://jsfiddle.net/Tu2GU/
See the titles, when a title has a long text, the heading goes under the floated div. I want the heading to break and then display 2 lines (or more) and stay on the left of the floated div, not under it.
Can't find anything helping, thanks !
edit : i updated the jsfiddle : http://jsfiddle.net/Tu2GU/13/ (removed % width for the floated div)
I don't want to have 2 divs side by side, the floated div on the right is meant to be right there, like a page summary giving link inside the page.
Also, heading are under the floated div (in html code) not over.
Since the right list uses a percent width, you can set a max-width with a percent width
h2 {
... Your original CSS ...
max-width:calc(75% - 40px); /* 40px comes from horizontal padding */
}
Demo
I'd recommend using a class to apply to each header instead of using the same max-width on each h1, h2, etc, but that's just personal preference
If the width of the right floated div is set, use calc(100% - 440px) or whatever the left horizontal padding + right width is
Create a float: left; container using the CSS below:
.lfloat {
float: left;
width: 75%;
}
You just have to wrap your text in a new div:
<div class="lfloat">
<!-- content -->
</div>
Demo
This will contain the content to the left and keep your sidebar to the right.
Note: You must clear your floats with clear: both;.
Why not try floating the elements on the left instead of using inline-block?
* {
font-family: Tahoma, Geneva, sans-serif;
font-weight: normal;
font-size: 1em;
}
.rfloat {
float: right;
width: 25%;
background: #9C3;
color: #111;
}
h1 {
float: left;
margin: 0;
padding: 10px 5%;
background: #06C;
color: #FFF;
}
h2 {
float: left;
margin: 0;
padding: 10px 5%;
background: #F33;
color: #FFF;
width:65%;
}
http://jsfiddle.net/g4Grv/
updated your Jsfiddle: http://jsfiddle.net/Tu2GU/12/
Main thing was a wrapping div around your h1 and p tag alongside of display:inline-block and vertical-align:top
Is this what you needed?
You have a few options. You can float the heading to the left so that it will slide up - you will have to set a width, though.
h2 {
float: left;
width: 80%;
}
Another option would be to set a max width. Since inline-block elements are technically block level, you can supply a width without breaking anything. You could try this:
h2 {
max-width: 80%
}
Yet another option would be to make the element inline. This will let the browser determine the best fit for the header.
h2 {
display: inline;
}
This will make the header wrap around the list and you may get the results you want. This method will make height and width parameters not work, so you will have to substitute those for line-height and padding

CSS: Background color to text size

I'm would like to color the background of a text but only to it's size.
Images are better than a thousand words, here is what I'm trying to achieve:
And this is what I am achieving
I don't want to do this programmatically, I would like the background to adapt to the text ( because it may be dynamic )
Is there anyway to do this without using javascript?
Update (HTML):
<div class="team-member-teaser-name">OSCAR</div>
CSS
.team-member-teaser-name
{
color: #4fb4d0;
background: #135364;
margin-top: 5px;
margin-bottom: 5px;
padding-left: 5px;
font-size: 10px;
}
Update (Solved, based on #BoldClock answer):
.team-member-teaser-name
{
color: #4FB4D0;
background: #135364;
margin-top: 5px;
padding-left: 5px;
font-size: 10px;
display: inline;
float: left;
padding-right: 9px;
clear: both;
}
I don't really understand how clear works, but is required to achieve the results on the image.
You need to apply the background color to an inline element. If the text is in a block element, you need to wrap the text in an inline child of the block element (assuming it's not feasible to put display: inline on the block element). And if you can't edit the HTML, you will have to do it within a script.
You could wrap your text in a span like this:
<p><span class="highlight">OSCAR</span></p>
and then, depending on you current css you could style it like this:
.highlight{
background-color: blue;
}
Use the background property to define a background color. For eg,
oscar
a{ background:#ff0000; }
If you have inline elements such as a <span /> or <a /> you can add display:block to the styles if you want to define a height and width on the element. Additionally, you can also define a padding on the element if you want to control the spacing area around the text to give your text some breathing room.

In CSS, what is a better way of forcing a line break after an element than making it a block element?

I have an H3 heading that I'd like to style as having a particular background color, but without having the element's background take up the full width of the parent element. Seeing as H3 is by default a block element, my style would need to change the element to an inline-block element, or just an inline inline element like so:
h3 {
background-color: #333;
color: white;
display: inline-block;
}
This will work fine, but only if it is immediately followed by a block element. I do not want to change the markup just to cater for this style, so I was wondering if there is a way to cause any adjacent element, irrespective of how it displays, to start on the next line?
Assume I can use CSS3.
try this:
h3:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
display:block;
width:auto;
This will make the width as small as possible (not filling the whole parent element) and make other elements appear below.
How often does it happen that the element after the <h3> is an inline element? (Usually after a header there should be like a <p>, <ul> or other block elements, although this totally depends on your html. Is it predictable? Is it an option to just turn every element that directly follows a <h3> into a block element?
h3 ~ * { display: block }
The only other way I know to have a block-element not take up all the space is floating it, but this leaves another problem.
I come across this all the time in my code, usually for div's that are inline-block'ed. The best way I've seen is to force a new line is to wrap your code in an additional div. Your original html gets the formatting you expected and the div wrapper forces a new line.
Assuming this is your h3 styling,
h3 {
display: inline-block;
}
Then just wrap it in a div.
<div>
<h3>My heading</h3>
</div>
I've had to do something similar with inline nav items that need breaking at certain points. Does this work?
h3:after {
content: "\A ";
line-height: 0;
white-space: pre;
display:inline-block;
}
I seem to remember IE7 having an issue with it.
If you don't need to center h3, this may help:
h3 {
background-color: #333;
color: white;
display: inline-block;
float: left;
clear: left;
}

align icons with text

What's the best way to align icons (left) and text (right) or the opposite text on left and icon on right?
Does the icon image and text have to be the same size? Ideally I would like them to be different but be on the same vertical alignment.
I am using background-position css property to get the icons from a larger image.
Here is how I do it now, but I am struggling with either getting them to be on the same line or be vertically aligned to the bottom.
Text
This is what I get after I try your suggestions.
Though the text is now aligned with the icon, it is superimposed over the icon to the right of the icon that I want. Please note that i am using the background position to show the icon from a larger set of images.
Basically I am getting
<icon><10px><text_and_unwanted_icon_to_the_right_under_it>
<span class="group3_drops_icon group3_l_icon" style="">50</span>
group3_drops_icon {
background-position:-50px -111px;
}
.group3_l_icon {
-moz-background-clip:border;
-moz-background-inline-policy:continuous;
-moz-background-origin:padding;
background:transparent url(/images/group3.png) no-repeat scroll left center;
height:35px;
overflow:hidden;
padding-left:55px;
}
I usually use background:
<style type="text/css">
.icon {
background-image: url(path/to/my/icon.jpg);
background-position: left center;
background-repeat: no-repeat;
padding-left: 16px; /* Or size of icon + spacing */
}
</style>
<span class="icon">Some text here</span>
You can do it on the same line using vertical-align and line-height
<p style='line-height: 30px'>
<img src='icon.gif' style='vertical-align: middle' />Icon Text
</p>
Alternatively, you can go the background approach with no-repeat and positioning:
span.icontext {
background: transparent url(icon.gif) no-repeat inherit left center;
padding-left: 10px /* at least the width of the icon */
}
<span class="icontext">
Icon Text
</span>
Sadly, neither of these answers are bullet proof and each have one big flaw.
#rossipedia
I used to implement all my icons this way and it works quite well. But, and this is a big but, it does not work with sprites, since you're using the background-position property to position the icon inside the container that includes your text.
And not using sprites where you can is bad for performance and SEO, making them imperative for any good modern website.
#Jamie Wong
The first solution has two markup flaws. Using elements semantically correctly is sadly underrated by some, but you'll see the benefits in prioritizing form in your search engine ranking. So first of all, you shouldn't use a p-tag when the content is not a paragraph. Use span instead. Secondly, the img-tag is meant for content only. In very specific cases, you might have to ignore this rule, but this isn't one of them.
My Solution:
I won't lie to you, I've checked in a lot of places in my time and IMHO there is no optimal solution. These two solutions are the ones that come closest to that, though:
Inline-Block Solution
HTML:
<div class="container">
<div class="icon"></div>
<span class="content">Hello</span>
</div>
CSS:
.container {
margin-top: 50px;
}
.container .icon {
height: 30px;
width: 30px;
background: #000;
display: inline-block;
vertical-align: middle;
}
.container .content {
display: inline-block;
vertical-align: middle;
}
"display:inline-block;" is a beautiful thing. You can do so much with it and it plays very nicely with responsive design.
But it depends on your client. Inline-Block does not work well with IE6, IE7 and still causes problems with IE8. I personally no longer support IE6 and 7, but IE8 is still out there. If your client really needs his website to be usable in IE8, inline-block is sadly no option. Assess this first. Replace the black background of the icon-element with your sprite, position it, throw no-repeat in there and voilà, there you have it.
Oh yeah, and as a plus, you can align the text any way you want with vertical-align.
P.S.: I am aware that there's an empty HTML-tag in there, if anyone has a suggestion as to how to fill it, I'd be thankful.
Fixed Height Solution
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix {
display: inline-block;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}
.container {
margin-top: 50px;
border: 1px solid #000;
}
.container .icon {
height: 30px;
width: 30px;
background: #000;
float:left;
}
.container .content {
line-height: 30px;
float: left;
display: block;
}
I hate this one. It uses a fixed line height for the text, and if you choose the same height as the Icon's box, the text is centered to that height. To align the text to the top, cut the line height, and as to the bottom, you'll have to fix that with position: absolute and a fixed width and height for the container. I'm not going to get into that unless someone requests it, because it's a whole issue for itself, and brings with it a lot of disadvantages.
The main disadvantage of this path is the fixed height. Fixed heights are always unflexible and especially with text, it can cause a bunch of problems (You can no longer scale the text as a user without it being cut off, plus different browsers render text differently). So be sure that in no browser the text is cut off and that it has some wiggle room inside its line height.
P.S.: Don't forget the clearfix for the container. And, of course, replace the black background with your sprite and according position + no-repeat.
Conclusion
Use inline-block if at all possible. ;) If it's not, breath deeply and try the second solution.

Resources