When you increase the line-height of an element, you start getting gaps between each line of text. Most of the time this is fine, since you don't see the specific gap.
But it is problematic when you have a narrow column, with a link that runs over multiple lines. If you move your mouse over the link, there is a small gap between the lines, which makes the link hover effect flash on and off.
From a design/usability perspective, I feel this makes for a bad user experience (no one likes random flashing). Try it with this:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In est. Nunc aliquam, eros a aliquam consequat, ante diam rutrum risus, et dignissim ligula turpis et ante. Maecenas leo neque, euismod in, aliquam et, molestie ac, ligula. Integer venenatis. Pellentesque enim. Maecenas aliquet, tortor at molestie sodales, urna velit pulvinar lorem, ac malesuada nibh turpis eu tortor.
I can add some padding to links to prevent this happening in some cases, but it doesn't work when text is larger; I need more padding. Anyone have ideas for solutions?
Try fixing your flashing problem by setting display:block for your <a> element in that narrow column.
If you know the start and end point of each line you could put a span round each line, and turn it into an inline block
#wrap {font-size:14px; line-height:16px;}
a span{display:-moz-inline-block; display:inline-block;line-height:14px;padding:1px 0;}
a:hover {background:red;}
<div id="wrap">
dsvlaksvh; asvj asdfh;dhldv hd d dl h dfhd d dfh; daljfda k;d <a href="#" >
<span>hdv </span><span>dvh ldvhldf dhk </span><span>;dhkdf hdl hdfk
</span><span>dfhkldf h vkhg j</span></a> glj gj f gjl fjl fj f
</div>
Use relative units to set the padding.
Adding padding: 0.2ex 0; background: red; using Firebug/Dragonfly to the example link in the question works just fine for me, whatever the font size (set through CSS or zooming in).
The only problem with changing the font-size in Firefox is that the background starts overlapping the previous line; but that's a line-height issue.
Related
I am building a CSS Grid layout, and somehow I'm unable to get the "auto" value to work for the sizing of row height.
The items keep a minimum height of 1fr, even if their content is small enough to allow them to shrink.
Here is a code example that explains the problem - you can also check it out on https://codepen.io/16kbit/pen/RJbMWM
section {
display: grid;
grid-template-areas: "one top" "one bottom";
align-items: start;
border: 1px solid hotpink;
}
article {
border: 1px solid green;
}
#one {
grid-area: one;
}
#top {
grid-area: top;
}
#bottom {
grid-area: bottom;
background: yellow;
}
<section>
<article id=one>
<h1>One</h1>
<p>Lorem cool dolizzle sit amizzle, dope sizzle elizzle. Nullam shiznit velizzle, get down get down volutpizzle, suscipizzle quizzle, dizzle mammasay mammasa mamma oo sa, arcu. Pellentesque sheezy tortizzle. Sed erizzle. Fusce izzle dolor shiznit pimpin'
tempizzle tempor. Maurizzle pellentesque nibh shizzlin dizzle turpizzle. Vestibulum in tortor. Pellentesque cool rhoncus black. In hac fo shizzle my nizzle check out this dictumst. Black uhuh ... yih!. Mammasay mammasa mamma oo sa tellizzle shiz,
pretizzle shiznit, mattizzle fo, gangster vitae, nunc. Get down get down suscipizzle. Own yo' away izzle sed cool.Nullizzle fizzle shut the shizzle up yo mamma orci daahng dawg viverra. Phasellus nizzle shizzle my nizzle crocodizzle. Curabitizzle
sure velit vizzle check out this dizzle doggy. Maecenas sapien nulla, iaculis shiz, molestie hizzle, egestas a, erizzle. Shit vitae turpis quizzle nibh bibendizzle boom shackalack. Nizzle pulvinar dope velizzle. Aliquizzle mammasay mammasa mamma
oo sa volutpat. Nunc izzle its fo rizzle at lectus pretizzle faucibizzle. We gonna chung nec lacizzle own yo' fizzle pizzle ultricizzle. Ut nisl. Crunk et owned. Integer laoreet ipsum shizzlin dizzle mi. Donizzle at shiz.</p>
</article>
<article id=top>
<h1>Top</h1>
<p>Just Two Words</p>
</article>
<article id=bottom>
<h1>Bottom</h1>
<p>Help Me! How can I get closer to my Top neighbour?</p>
</article>
</section>
The result I want:
I want the #bottom item to move as close as possible to the #top item. And I want them to shrink to their contents size.
Actual result:
The CSS Grid doesn't allow the item's height to be smaller than 1fr unit (50% of the total height) – which is changing depending on the #one item, that has a lot of text.
Visual explanation: instead of the result on the left, I want the result on the right:
It appears, based on what you've written in your question and answer, that you are overlooking an important concept of grid layout (and grids, in general).
A row extends across an entire grid. It's not confined to a single column.
So when you write:
If we had three rows in our right column...
There's no such thing. All rows exist in all columns (and vice versa).
Here's an illustration of your layout from dev tools:
As you can see, all rows extend across all columns.
The height of the third row is set by the content in #one, just as you specified.
The third row in the right column must be the same height as the third row in the left column, because a row can only have one height.
However, you can adjust the size and alignment of grid areas within rows and columns.
align-self: stretch (default value)
align-self: end
align-self: center
align-self: start (what you may be looking for)
section {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto 1fr;
grid-template-areas:
"one top"
"one center"
"one bottom";
border: 1px solid hotpink;
}
article {
border: 1px solid green;
}
#one { grid-area: one;}
#top { grid-area: top;}
#center { grid-area: center;}
#bottom { grid-area: bottom; align-self: start; background-color: aqua;}
<section>
<article id=one><h1>One</h1><p>Lorem cool dolizzle sit amizzle, dope sizzle elizzle. Nullam shiznit velizzle, get down get down volutpizzle, suscipizzle quizzle, dizzle mammasay mammasa mamma oo sa, arcu. Pellentesque sheezy tortizzle. Sed erizzle. Fusce izzle dolor shiznit pimpin' tempizzle tempor. Maurizzle pellentesque nibh shizzlin dizzle turpizzle. Vestibulum in tortor. Pellentesque cool rhoncus black. In hac fo shizzle my nizzle check out this dictumst. Black uhuh ... yih!. Mammasay mammasa mamma oo sa tellizzle shiz, pretizzle shiznit, mattizzle fo, gangster vitae, nunc. Get down get down suscipizzle. Own yo' away izzle sed cool.Nullizzle fizzle shut the shizzle up yo mamma orci daahng dawg viverra. Phasellus nizzle shizzle my nizzle crocodizzle. Curabitizzle sure velit vizzle check out this dizzle doggy. Maecenas sapien nulla, iaculis shiz, molestie hizzle, egestas a, erizzle. Shit vitae turpis quizzle nibh bibendizzle boom shackalack. Nizzle pulvinar dope velizzle. Aliquizzle mammasay mammasa mamma oo sa volutpat. Nunc izzle its fo rizzle at lectus pretizzle faucibizzle. We gonna chung nec lacizzle own yo' fizzle pizzle ultricizzle. Ut nisl. Crunk et owned. Integer laoreet ipsum shizzlin dizzle mi. Donizzle at shiz.</p>
</article>
<article id=top><h1>Top</h1> <p>Just Two Words</p></article>
<article id=center><h1>Center</h1></article>
<article id=bottom><h1>Bottom</h1><p>Help Me! How can I get closer to my Top neighbour?</p></article>
</section>
After some more trial and error, I found a working solution:
grid-template-rows: auto 1fr;
When the last item has a value of 1fr, the other item is allowed to adapt it's size with auto.
If we had three rows in our right column, the working CSS would look like this:
grid-template-rows: auto auto 1fr;
The result of this would be: the two first items (auto) adapt according to their content, the third item (1fr) will fill any vertical space that is left.
In other words: you need one item to have a value of 1fr, in order for the other items to be fully flexible with auto.
Solution based on the others but without defined template areas.
Set grid-row: 1 / -1; for the main/primary content element.
https://codepen.io/gynekolog/pen/eYyGNma
Or responsive version by tailwind:
https://play.tailwindcss.com/h4RvbInNXB
I'm working with a bootstrap based site. I have a problem where we are trying to get the two column heights to be equal despite the size of the content inside the columns, and without setting a column height (to keep it responsive).
I have googled my brains out and decided that the display: table, display: table-cell is the appropriate way to fix this (we support IE9, so Flexbox is OUT, and the negative margin/padding thing breaks responsiveness). I have specific media queries to fix responsiveness based on screen size.
However, I am getting a single pixel of what appears to be padding on the left side of my smaller column in Safari (it looks perfect in IE, Chrome, Firefox and Edge). After looking through the inspector, I can tell that it's not margin or padding causing the pixel, so I'm not sure how to fix it. I tried border-collapse: collapse to no avail. If I remove the display: table or display: table-cell, it looks correct, but I need those to make the columns the same height (see example here). Any ideas? Code is below.
<style>
.row-tbl {
display: table;
}
.col-tbl-cell {
float: none;
display: table-cell;
}
.blue-bg {
background-color: blue;
}
.white-bg {
background-color: white;
}
</style>
<div class="row row-tbl">
<div class="col-md-4 col-tbl-cell blue-bg">
<!-- This displays as a table cell -->
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="col-md-8 white-bg">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ac tempus sem, nec luctus tellus. Integer erat urna, fermentum sit amet porttitor at, rhoncus non arcu. Aenean a libero consectetur metus imperdiet scelerisque at ut nibh. Sed mauris mauris, facilisis nec nulla at, cursus imperdiet magna.</p>
</div>
</div>
I can’t reproduce this issue in Safari 9 on OS X 10.11.2 with the code sample above, but it could be some kind of rounding error.
http://cruft.io/posts/percentage-calculations-in-ie/
You could try applying the left column’s background color to the row itself. If it goes away, then it might be a subpixel rendering issue.
Note: I think you’re missing the col-tbl-cell class on the second column ;)
I ended up pulling the row-tbl class onto a new div under the row and above the column. That worked!
Why the text or images are not placed behind a floating element?
On this link:http://codepen.io/anon/pen/LVWmvp, you can see the example. The "blue" div is placed behind the "transp" div.
But the thing is that the text (or an image) is not placed behind the "transp" div also. And please notice that the p tag is in the "blue" div.
So my question is: Why does this happen? Why the text is not placed behind the "transp" div like his parent?
I have been looking for an answer. But I couldnt find something to explaining this situation.
Could you please help me? :)
This is the code you will find on codepen.io:
HTML
<div id="transp">
</div>
<div id="blue">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam id dolor scelerisque, pellentesque arcu sed, vehicula enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis felis eros, accumsan eget erat non, vulputate blandit urna. Sed consequat nibh vitae lectus tempor viverra. Quisque condimentum, elit id pretium accumsan, quam nunc faucibus risus, id tincidunt massa est in turpis. </p>
</div>
CSS:
#transp{
border: 1px solid #000;
height:200px;
width:200px;
float:left;
}
#blue{
background-color:#00ffff;
height:200px;
width:600px;
}
This is what you will see:
The point of floating is to place an object beside a paragraph of text or other inline content, such that the content will flow around it. From the spec:
A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box.
Having text ignore a float would defeat the purpose of floating altogether.
The float is removed from normal flow, which is why the "blue" div is positioned as though the floating element were not there. As a result any text that flows vertically past the floating element will start directly underneath, rather than leaving a gap there. You can see this if you make your div narrower and taller (or remove the height declaration).
The simple answer: because you have a float:left on #transp. What this does is tell the browser that #transp should go to the left of the normal flow, force any subsequent block-elements (div) to tolerate it on the left. In effect, #transp becomes like an inline element, but with size.
This was the way to make things flow in a row before the advent of display: inline-block. These days, with more advanced css techniques, floats are typically considered bad practice for layout, so they should be avoided alongside tables.
Fiddle illustrating the problem - click the button a few times and the box will shrink, revealing the issue.
This issue appears to only happen in Internet Explorer.
Basically, when an element that contains white-space: pre-wrap is resized slowly, IE doesn't recalculate word wrapping, resulting in text being pushed outside the element. Some recalculating does happen, but not all of it. The more the element is resized, it seems, the more recalculation is actually done.
Zooming the page fixes the issue, but is obviously not a practical solution.
How can I force IE to recalculate word wrapping when the container's size changes?
New (ridiculous) HTML Change Solution (but works!)
Because of the odd first line failure, the solution depended upon generating a non-important first line and then accommodating it. This fiddle demonstrates what appears to be a now "bug free" solution for IE9 (some tweaking to account for my pseudo-element/class use would be needed for earlier IE versions).
The HTML requires an excessive amount of wrapping, such that each section of text is "double wrapped." The demo has three different means of gaining the block level wrap, but all use the same fix.
Essential HTML
<div id="cnt">
<p class="ieFixBlockWrap">
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tincidunt consectetur tortor, sed vestibulum lectus hendrerit at. Praesent fermentum augue molestie lectus pharetra eget cursus erat cursus.
</span>
</p>
<span class="ieFixBlockWrap">
<span>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent fringilla nisl posuere tortor rutrum lobortis.
</span>
</span>
<div class="ieFixBlockWrap">
<span>In risus libero, faucibus ac congue et, imperdiet ac purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi aliquam lobortis ullamcorper. Proin risus sapien, pulvinar in adipiscing non, rutrum hendrerit magna. Praesent interdum pharetra vehicula. Integer molestie mi neque.
</span>
</div>
</div>
CSS
#cnt {
white-space: pre-wrap;
border:1px solid black;
line-height: 1.2em; /* set explicitly, see below */
/* prevent shifted :before from interfering with elements preceeding #cnt */
overflow: hidden;
}
.ieFixBlockWrap:before { /* this becomes the first line, but also an extra line gap */
content:'';
display: inline-block;
width: 100%;
}
.ieFixBlockWrap {
display: block; /* just to demo span as block level */
margin: -1.2em 0; /* offset by line-height to remove gaps from :before*/
}
.ieFixBlockWrap:last-child {
margin-bottom: 0; /* last one does not need the bottom margin adjusted */
}
Original HTML Change Solution (still failed on first line)
Wrapping all the text in a single span inside the div set with pre-wrap seemed to make it behave in this fiddle.
It looks like you can force IE to redraw the container by removing the element and then adding it back (unfortunate you have to resort to this, but oh well). Here's a resize function that will do just that, along with a fiddle to see it in action:
var resize = function(element, changeWidth, changeHeight){
changeWidth = parseInt(changeWidth) || 0;
changeHeight = parseInt(changeHeight) || 0;
element.style.width = (parseInt(element.style.width) + changeWidth) + 'px';
element.style.height = (parseInt(element.style.height) + changeHeight) + 'px';
var parent = element.parentNode;
parent.removeChild(element);
parent.appendChild(element);
};
See the notes in the blue areas on the page below to see what I am trying to achieve.
http://www.a3financial.com/subtitleproblem.php
Here I have 2 p's which are subtitles, illustrated in blue, which I'm wanting to fluidly be as wide as possible within the fixed-width content area, while respecting any float:left image's padding/margin.
From what I understand this is the expected behavior when you don't set any width for the p and do have one set for the float:left.. but for some reason my subtitles' background are going behind the image and not respecting its' margins. Perhaps I'm wrong on my expectation. I know liquid widths with floats are difficult/impossible to achieve. Is there any way to do this?
For clarity, I want the page to look like this. I've added borders for additional clarity.
http://a3financial.com/images/clarity.png
To my knowledge, this is all that is being applied to the float:right:
#content .subtitle {
padding-top: 2px;
float: right;
background-color: #8FD2E3;
letter-spacing: -1px;
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
color: #969696;
}
And here is the code for the float:left:
img.alignleftimg {
float: left;
width: 163px;
/*margin-right: 30px;F*/
padding-right: 30px;
}
HTML (apologies for long latin, text is needed to illustrate flow):
<p class="subtitle">Subtitle 1 - should be as wide as possible, respecting the image's padding/margin.</p>
<img src="images/homepage09.jpg" alt="" width="163" height="163" class="alignleftimg" />
<p>nunc nisl velit, fringilla ut ornare non, iaculis in ipsum. Vivamus volutpat quam et dui vestibulum ultricies. Fusce vitae sapien sed ipsum hendrerit dignissim. Lorem ipsum dolor at tellus. Etiam vitae ligula non ante iaculis. Curabitur elementum diam nec etiam lorem ipsum mauris dapibus arcu, sed bibendum libero elit et sem. Nunc at nunc tortor, ut aliquam augue. Etiam ut sem quis tellus iaculis convallis. Nulla viverra, metus eget accumsan. Maecenas pede nisl, elementum eu, ornare ac, malesuada at, erat. Proin gravida orci porttitor enim accumsan lacinia. Donec condimentum, urna non molestie semper, ligula enim ornare nibh, quis laoreet eros quam eget ante. Quisque erat. Vestibulum pellentesque, justo mollis pretium suscipit, justo nulla blandit libero, in blandit augue justo quis nisl. Fusce mattis viverra elit. Fusce quis tortor. Aliquam libero. Vivamus nisl nibh, iaculis vitae, viverra sit amet, ullamcorper vitae, turpis. Aliquam erat volutpat. Vestibulum dui sem, pulvinar sed, imperdiet nec, iaculis nec, leo.Pellentesque tristique ante ut risus. Quisque dictum. Integer nisl risus, sagittis convallis, rutrum id, elementum congue, nibh. Suspendisse dictum porta lectus. Donec placerat odio vel elit. </p>
<p class="subtitle">Subtitle 2 - should also be as wide as possible, pushing text out of the way in this case, to fill 100% of body width.</p>
<p>Aliquam libero. Vivamus nisl nibh, iaculis vitae, viverra sit amet, ullamcorper vitae, turpis. Aliquam erat volutpat. Vestibulum dui sem, pulvinar sed, imperdiet nec, iaculis nec, leo. Fusce odio. Etiam arcu dui, faucibus eget, placerat vel, sodales eget, orci. Donec ornare neque ac sem. Mauris aliquet.</p>
edit: starting to think i'm using the wrong element for this.. perhaps an h2 would function as i'm intending.. continuing to research.
edit 2: it doesn't appear h2 has any discernible difference from using p.
edit 3: added an image to clarify what i'm after.
final edit: Found what I was looking for and answered the question myself! Adding overflow:auto; to the subtitle class made its' background respect the float's margin and padding! See the accepted answer. Cleaned up the question for those searching in the future, as initially I didn't understand how to use floats correctly. Here's a link to the final product:
http://www.a3financial.com/subtitletest.php
OK, a couple of things first:
float applies to how a block elment is rendered with respect to the text of the main document. Float is not intended to be a way to control the size or positions of the actual elements themselves.
The best way to see this is an example:
<div id="A" style="float:right;background-color:#0f0;height:20px;">
my title
</div>
<div id="B" style="background-color:#00f;height:35px;">
my impressive language skills
</div>
Then this means that div A will float left of the content(text) in the document's main flow (div B is in the main flow). This does not affect the physical size of either div A or div B. You will see that in this example, div B is 100% wide (the backgrounds mark the container's actual size). Div's default behavior is to take up 100% of the available width of its container.
Div A is only as big as it needs to display it's content, so it may seem that its behavior is differnet. This is not really the case though. Because div A floats, it is rendered in its own virtual container outside of the main document. The fake container is set to be the minimum size possible, which is basically 0% wide. So, like any 0% continer, it stretches as much as necessary to accomidate the contents within). In effect, div A is 100% wide in a container that is 0% wide (by default).
You should also note that in this example, div A is not just floating to the right of the content within div B, but it is floating right in regards to ALL content in the main document flow. This is where a div with the "clear:both;" css attribute comes in handy, as this ensures that things that are floating stop floating at a specific point in the document (content that would have floated is pushed down).
Now, when we look at your document in particualr, what your were effectivly trying to do was stack 3 floats with each other... A floating right of B, and B floating left of C. But the containers themselves will just be however big they need to be. This gets very hard to manage, and can be unpredictable on different browsers... and you end up trying to manage everyting's width, height, padding, and margin plus doing all kinds of other still just to keep the containers from overlapping and piling up on top of each other.
The best bet when using floats for positioning, is to ensure that within any one container, you have no more than one thing floating. So in your document's case, something like this:
.subtitle {
padding-top: 2px;
background-color: #8FD2E3;
letter-spacing: -1px;
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
color: #969696;
}
img.alignleftimg {
float: left;
width: 163px;
/*margin-right: 30px;F*/
padding-right: 30px;
}
Note that in this CSS, only the image is setup to float. The subtitle doesn't need to float because you always want it 100% wide relative to whatever container contains it.
Then for HTML:
<img src="images/homepage09.jpg" alt="" width="163" height="163" class="alignleftimg" />
<div class="section">
<p class="subtitle">Subtitle 1</p>
<p>
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
my impressive language skills
</p>
</div>
<div style="clear:both;"></div>
<div class="section">
<p class="subtitle">Subtitle 2</p>
<p>Aliquam libero. and some other stuff</p>
</div>
Note here that we used a div to group the subtitles and the text to which that subtitle applies into one content container (section). The image is set to float left starting at the first section, so all the text will slide out of the way. We use a clear div to make sure that we stop floating at this point, then we start the container for the next subtitle and text.
As with anything in HTML, the less you specify the better off you are. Instead of managing sizes, floats, positions, and all that junk I recommend that you specify as little as is possible in CSS. It's a subtle art, but it pays off.
Now, in the example I give, the content area's container and the image actually overlap. So if you try background styles, or borders, etc. it can get ugly. So, this is when you might want to specify widths and margins to control the containers themselves; but this is easier is you are careful to keep floating down to just one element within any one container.
You could elminiate container overlap in the above by adding in this CSS (in addition to what was already there):
img.alignleftimg + div.section{
margin-left: 170px;
}
This is an unusual css selector called the adjacent sibling selector... basically it says, "Applies to all div elements with a class-name of "section", that is also an immediate sibling to an img element with a class-name of "alignleftimg".... blah! Anyway, I just set the margin to a value a little bigger than the width of the image, and overlap is eliminated ONLY in the very specific case we want.
You might want to look at the HTML 5 section element; but I didn't use it here because it is a semantic element and so cross-browser support requires a bit more than just replacing the div tags with section tags.
Also, I want to point out that this entire discussion is the fault of the W3C. We needed real layout mechanisms that did the job of HTML layout tables way back in 1994... 18 years later, CSS grid is STILL not finalized and is probably another 10 years from being widly supported in shipping browsers.
Turns out this is possible!
By adding overflow: auto; to the subtitle class, it forces it to respect the image's margin and padding! Additionally, adding it to unordered lists has the added benefit of making sure the list stays in-line horizontally until it's complete before word-wrapping around the image.
See my final product here:
http://www.a3financial.com/subtitletest.php
Thanks to the following thread for pointing me in the right direction. I'd given up but happened to stumble upon it looking for a somewhat different issue:
Floated image to left of a ul is ignoring margin/padding
To make HTML elements fluid widely, You must set CSS width to:
width:**percent**%
While percent keyword is number between 0 and 100.
This is a calculation. Calculate the padding and margin to set the correct width percent.
For example:
Setting 3 fluid divs with no Padding or Margin:
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
CSS
.first, .second, .third{
float:left;
width:33%;
}
Hope this helps you.