Prevent "fragmentation" of wrapped text next to floated image - css

I'm trying to get this text to not "fragment" on smaller resolutions. It's for an assignment, and I'm restricted to using XHTML.
The image to the right is floated like this:
#image {
width:420px;
margin-left: 2%;
height:370px;
position:relative;
float:right;
}
with the XHTML:
<div id="image">
<a href="http://en.wikipedia.org">
<img src="picture.png"/>
</a>
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
Obviously this "fragmentation" doesn't appear on larger resolutions.
Is there an elegant way to this in CSS2.1?

Since the wrapping issue is resolution dependent, you can solve this pretty easily with CSS Media Queries. Think of these as a simple "if/else" for css.
So figure out the window width where the wrapping becomes unacceptable and create a max-width rule with that number. This means for width's less than your max size, the rule will apply.
Now at this size, simply remove the float and set the image to display block which will push the text down the page.
#media (max-width: 600px) {
#image {
display:block; // make image push text down
float: none; // remove your float
margin: 10px auto; // center the image in the available space
}
}
Note: With media queries should be at the BOTTOM of your CSS so they override the previous rule AND you only need to change the attributes that are overridden.

Nice solution #BryceHowitson.
I have just been grappling with this problem and came up with a variant on your approach. I put the Media query on the paragraph of text that followed the image.
My solution targets the clear property on the paragraph that follows the floated image. When the screen resolution leaves enough space beside the floated image for satisfactory rendering of the text, the paragraph wraps around the image. When the available width is too low for satisfactory rendering of the text, the paragraph has "clear:both" applied and the paragraph moves down below the floated image.
One 'pro' for this approach is that the CSS rule is applied to the element whose behavior we are trying to control.
However, what #BryceHowitson's solution achieves, and mine doesn't, is the centering of the image when the wrapping of the subsequent text is turned off.
CSS
.p-clear {
#media (min-width: 400px) {
clear: none;
}
#media (max-width: 400px) {
clear: both;
}
}
HTML
<img src="..." width="300px">
<p class="p-clear">text that needs at least 100px width</p>

Related

Conditionally apply styles based on component's own width?

The top-level container on my site has a max-width to keep it a reasonable size on wide screens. I have a dynamically sized component which can potentially be wider than that max-width. Normally, the component overflows off the side of the screen with it's own independent scrollbar. But on wide screens, with the max-width, the component is cropped by the side margins and it doesn't look great.
I've got a set of styles which can effectively override the top-level max-width and instead left-justifies the component and makes it use the viewport width instead of the top level max-width. It's as follows:
.wide-content {
width: fit-content;
max-width: 100vh;
position: relative;
left: calc(-50vw + 50%);
}
The problem now is that this class is unsuitable when the component isn't too wide. It's left justifying when the component would've fit just fine within the container. I only want those components which would be wider than the container to display this way.
Is there a way to conditionally apply this class, or at least just the left property, based on the components own width? Ie. Only apply that left style if the component is wider than top-max-width?
I'd rather avoid using JS for simplicity sake, but I am using scss if that makes it simpler. I'd take a JS solution if it's the only way, but that's a last resort.
Edit for clarification, here are some pictures of what I'm describing. The cream-colored boxes (labeled Main and Main #2) are the components which get the above styles:
What it looked like originally, without the above styles and with the cropping I don't like:
What it looks like with those styles applied unconditionally:
What I want, ie. the small box displays as it did originally but the large box gets the left-justification treatment:
I'm not sure whether this is what you're looking for, but checkout this
* {
margin: 0;
padding: 0;
}
:root {
--container-max: 300px;
}
.container {
background: lightcoral;
width: var(--container-max);
margin: 0 auto;
}
.graph {
background-color: yellowgreen;
white-space: nowrap;
overflow: visible;
min-width: fit-content;
transform: translate(calc((var(--container-max) - 100%) / 2), 0);
}
<div class="container">
<h1>An H1 Heading</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit odio voluptatum minima architecto a omnis at iure sint officia neque sapiente quos cupiditate similique illum doloribus, accusantium natus enim! Et.
</p>
<div class="graph" contenteditable>Lorem ipsum dolor sit amet</div>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit odio voluptatum minima architecto a omnis at iure sint officia neque sapiente quos cupiditate similique illum doloribus, accusantium natus enim! Et.
</p>
</div>
The green block is contenteditable, so start typing into it and you'll see its width eventually expands past the outer container, remaining centered in the screen.

Responsive CSS grid with scrollable cell overflows its parent container

I have a classic "top navigation bar - sidebar - main content" CSS grid layout which is also responsive and on smaller screens the sections are re-arranged vertically. The grid is styled to stretch out to the entire viewport. The main area is vertically scrollable if the content is longer than the viewport, whereas the top and side navigation bars are "pinned" to their positions and can't get smaller than their content in either direction.
To achieve the vertical scrolling in the main area, I've set the max-height property of the grid container to 100vh, and set the overflow-y property of the main element to auto. This max-height property, however, seems to have an adverse side-effect on the grid: the content can vertically overflow the grid container once the viewport's height becomes smaller than the minimum needed space to display the top navigation bar and sidebar (that can't shrink below their content).
This is what it looks like, for example, on a smaller screen, where the grid cells are stacked on top of each other:
The yellow overlay on the picture above is the scrolled-out part, not visible in the browser window. The main area is at the bottom with zero height (plus the border) but this is okay, as the main element is vertically scrollable and the grid row is set to have 1fr height. The black border is for the entire grid container. As the example shows, the sidebar and the main area is outside of the container.
The same thing on a larger screen, where the sidebar is moved to the left, looks like this:
What I would like to have, however, is that the grid cells don't overlap with the grid container but they are fully contained. That is, on a smaller screen with vertically stacked cells, this:
And on larger screens, with the sidebar on the left:
Can this be achieved using some modified version of the grid structure and CSS given below in the code snippet? So basically I would like to have a scrollable main area with top navigation bar and sidebar which can't shrink vertically below their minimum required height, and a grid container that doesn't overlap with its content. I'd like to avoid anything explicitly sized to a specific value (i.e. I would not like to use something like height: 120px.
Note, that this is a follow-up question on my previous one but it's not the same because I now have the requirement of a scrollable main area.
* {
box-sizing: border-box;
}
body {
margin: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.bordered {
border-style: solid;
border-width: 5px;
}
/* grid layout */
.grid {
display: grid;
/* Default (small screen) layout. */
/* Single column with 3 rows, the last one filling out the remaining space. */
grid-template-rows: min-content min-content 1fr;
max-height: 100vh;
min-height: 100vh;
min-width: min-content;
}
#media (min-width: 640px) {
.grid {
/* Larger screen layout. */
/* 2 columns with 2 rows, the bottom right cell filling out the remaining space. */
grid-template-columns: max-content 1fr;
grid-template-rows: min-content 1fr;
}
nav {
grid-column: span 2 / span 2;
}
}
aside, nav {
white-space: nowrap;
}
main {
overflow-y: auto;
}
<html>
<body>
<div class="grid bordered" style="border-color: black;">
<nav class="bordered" style="border-color: green;">Top nav</nav>
<aside class="bordered" style="border-color: red;">
<ul>
<li>Some example sidebar item #1</li>
<li>Some example sidebar item #2</li>
<li>Some example sidebar item #3</li>
<li>Some example sidebar item #4</li>
<li>Some example sidebar item #5</li>
</ul>
</aside>
<main class="bordered" style="border-color: cyan;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</main>
</div>
</body>
</html>
A colleague of mine suggested to use the overflow-y: auto property on the grid container itself. While its effect is not exactly the same as I was looking for, it's very similar and it does prevent the sidebar content from overflowing the container. The only minor difference is that when the available space becomes smaller than the necessary minimum to display the content of the grid, it's the grid container that gets a vertical scroll bar instead of the viewport.
Below is the modified code snippet that demonstrates it.
* {
box-sizing: border-box;
}
body {
margin: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.bordered {
border-style: solid;
border-width: 5px;
}
/* grid layout */
.grid {
display: grid;
/* Default (small screen) layout. */
/* Single column with 3 rows, the last one filling out the remaining space. */
grid-template-rows: min-content min-content 1fr;
max-height: 100vh;
min-height: 100vh;
min-width: min-content;
overflow-y: auto; /* <-- the only property added to the original CSS */
}
#media (min-width: 640px) {
.grid {
/* Larger screen layout. */
/* 2 columns with 2 rows, the bottom right cell filling out the remaining space. */
grid-template-columns: max-content 1fr;
grid-template-rows: min-content 1fr;
}
nav {
grid-column: span 2 / span 2;
}
}
aside, nav {
white-space: nowrap;
}
main {
overflow-y: auto;
}
<html>
<body>
<div class="grid bordered" style="border-color: black;">
<nav class="bordered" style="border-color: green;">Top nav</nav>
<aside class="bordered" style="border-color: red;">
<ul>
<li>Some example sidebar item #1</li>
<li>Some example sidebar item #2</li>
<li>Some example sidebar item #3</li>
<li>Some example sidebar item #4</li>
<li>Some example sidebar item #5</li>
</ul>
</aside>
<main class="bordered" style="border-color: cyan;">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</main>
</div>
</body>
</html>

Susy 2: background color on a nearby gutter

OK, first of all I tried to show the issue with Sassmeister, but it's so f... slow to compile that I just gave up. I use Susy, SCSS and Haml.
So here is the image that I think is relevant. I want to make the black bar at the top (background-color) to touch the black sidebar at the side. In other words - to add background color to gutter.
Here's my code:
HTML:
<div class="page">
<div class="nav">
<div class="brand">
<a class="name" href="/">Tomasz Gałkowski</a>
</div>
<div class="work">
<a class="projects" href="#">projects</a>
<a class="timeline" href="#">timeline</a>
</div>
<div class="blog">
<a class="articles" href="#">articles</a>
<a class="about" href="#">about me</a>
<a class="contact" href="#">contact</a>
</div>
</div>
<div class="content">
<div class="header">
<h1>Tomasz Gałkowski</h1>
<h2>web developer</h2>
</div>
<div class="main">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div class="footer">
<small>Tomasz Gałkowski, 2016</small>
<p>gitlab, facebook, twitter</p>
</div>
</div>
</div>
And (relevant) SCSS:
$susy: (
columns: 12,
gutters: 1/2,
debug: (image: show)
);
.page {
#include container;
#include clearfix; // from compass
}
.nav {
#include span (3 of 12);
background: $background-dark;
height: 100vh;
}
.content {
#include span(last 9 of 12);
background: $white;
.header {
background: $background-dark;
}
}
I was trying some stuff with bleed() or gutters() but it just didn't work the way I wanted it to work. I'm just starting to learn Susy and though I crawled through the whole documentation I wasn't really able to grasp this concept. :)
Susy doesn't really consider colors you'd want for gutters, as they are paddings or margins between grid elements.
The gutter between the nav and .content elements is just a margin between elements.
As the picture above illustrates, between the dark-yellow and the pink-ish elements, there is just a margin.
You can achieve having $background-dark as a background in the shape you described if you add the background to the container wrapper, being .page (that's the element you see between your columns) - the green element on the illustration. By then putting white background on the blue elements you want (.main and .footer), you'll pretty much be there.
Depending on what you're after with the space beneath .footer you may need to extend it's height somewhat, since .page will be visible.
If you're really set on not putting a background on .page, you could use the pseudo element &:before of .content to overlay the gutter between your columns. If feels like patch-work and I wouldn't recommend it.
Even though miphe's answer goes more in-depth I decided to add this one as well to be more case-specific. After some research I decided that what I was trying to achieve is an anti-pattern.
What I did to get the result I wanted to get: I set fixed width on the sidebar and used .content as #include container; instead of .page and moved .content to the right by setting padding-left: $sidebar-width where $sidebar-width is the fixed value.

What is the difference between display: inline and display: inline-block?

What exactly is the difference between the inline and inline-block values of CSS display?
A visual answer
Imagine a <span> element inside a <div>. If you give the <span> element a height of 100px and a red border for example, it will look like this with
display: inline
display: inline-block
display: block
Code: http://jsfiddle.net/Mta2b/
Elements with display:inline-block are like display:inline elements, but they can have a width and a height. That means that you can use an inline-block element as a block while flowing it within text or other elements.
Difference of supported styles as summary:
inline: only margin-left, margin-right, padding-left, padding-right
inline-block: margin, padding, height, width
display: inline; is a display mode to use in a sentence. For instance, if you have a paragraph and want to highlight a single word you do:
<p>
Pellentesque habitant morbi <em>tristique</em> senectus
et netus et malesuada fames ac turpis egestas.
</p>
The <em> element has a display: inline; by default, because this tag is always used in a sentence.
The <p> element has a display: block; by default, because it's neither a sentence nor in a sentence, it's a block of sentences.
An element with display: inline; cannot have a height or a width or a vertical margin. An element with display: block; can have a width, height and margin.
If you want to add a height to the <em> element, you need to set this element to display: inline-block;. Now you can add a height to the element and every other block style (the block part of inline-block), but it is placed in a sentence (the inline part of inline-block).
One thing not mentioned in answers is inline element can break among lines while inline-block can't (and obviously block)! So inline elements can be useful to style sentences of text and blocks inside them, but as they can't be padded you can use line-height instead.
<div style="width: 350px">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<div style="display: inline; background: #F00; color: #FFF">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<hr/>
<div style="width: 350px">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<div style="display: inline-block; background: #F00; color: #FFF">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
All answers above contribute important info on the original question. However, there is a generalization that seems wrong.
It is possible to set width and height to at least one inline element (that I can think of) – the <img> element.
Both accepted answers here and on this duplicate state that this is not possible but this doesn’t seem like a valid general rule.
Example:
img {
width: 200px;
height: 200px;
border: 1px solid red;
}
<img src="#" />
The img has display: inline, but its width and height were successfully set.
splattne's answer probably covered most of everything so I won't repeat the same thing, but: inline and inline-block behave differently with the direction CSS property.
Within the next snippet you see one two (in order) is rendered, like it does in LTR layouts. I suspect the browser here auto-detected the English part as LTR text and rendered it from left to right.
body {
text-align: right;
direction: rtl;
}
h2 {
display: block; /* just being explicit */
}
span {
display: inline;
}
<h2>
هذا عنوان طويل
<span>one</span>
<span>two</span>
</h2>
However, if I go ahead and set display to inline-block, the browser appears to respect the direction property and render the elements from right to left in order, so that two one is rendered.
body {
text-align: right;
direction: rtl;
}
h2 {
display: block; /* just being explicit */
}
span {
display: inline-block;
}
<h2>
هذا عنوان طويل
<span>one</span>
<span>two</span>
</h2>
I don't know if there are any other quirks to this, I only found about this empirically on Chrome.
inline elements
Have respect for their left & right margin and padding. not for top/bottom.
Cannot set width or height.
Allow other elements to sit to their left and right.
Inline-Block elements:
Respect all sides for margin and padding.
Can set width and height.
Allow other elements to sit to their left & right.
Block elements:
Respect all sides for margin and padding
Acquire full-width (in case the width is not defined)
Force a line break after them
A visual example looks like this:
Check out the snippet below for an extra visualization example
.block{
background: green;
width: 50px;
height: 50px;
margin-top: 10px;
margin-bottom: 10px;
display: block;
}
.inline-block{
background: green;
width: 50px;
height: 50px;
margin-top: 10px;
margin-bottom: 10px;
display: inline-block;
}
.inline{
background: green;
width: 50px;
height: 50px;
margin-top: 10px;
margin-bottom: 10px;
display: inline;
}
<div class="block">
block
</div>
<div class="block">
block
</div>
<div class="inline-block">
inline block
</div>
<div class="inline-block">
inline block
</div>
<div class="inline">
inline
</div>
<div class="inline">
inline
</div>
Block - Element take complete width.All properties height , width, margin , padding work
Inline - element take height and width according to the content. Height , width , margin bottom and margin top do not work .Padding and left and right margin work. Example span and anchor.
Inline block - 1. Element don't take complete width, that is why it has *inline* in its name. All properties including height , width, margin top and margin bottom work on it. Which also work in block level element.That's why it has *block* in its name.

Different Layouts in IE8 on Different Web Servers

Last night, I experienced a strange behavior in IE8 as I saw two noticeably different layouts of a page that's being hosted on separate servers. On my local web server, the header markup looked as expected with its left aligned logo and right aligned and stacked utility links, all of which displayed on a centered page. On a staging web server and a production web server, the header markup was completely invisible on the page, as it was positioned 152px higher than the page.
I understand that the ".header .hog" selector CSS code below is a hack. It was a quick fix for changes that needed to get deployed immediately. Rather than analyzing how to improve this code, I'm more interested in knowing the cause(s) of these presentation differences in IE8. A few question that I have are:
Could the markup have different encoding? If so, what is the best way in determining this possibility? And, which setting, if any, in IIS7 is responsible for encoding output?
Could permissions be the cause of this problem?
Is there a feature in IIS7 that determines whether or not the markup is strictly interpreted?
Is there a difference between the Layout Engines of IE8 on Vista and IE8 on XP?
My markup code is as follows:
<body>
<div class="content">
<div class="header">
<h1 id="logo"><img src="/img/logo.jpg" /></h1>
<div class="hog">
<a class="see">Text</a>
<div class="more">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
<div class="utility-links">
<a>link1</a>|
<a>link2</a>|
<a>link3</a>|
<a>link4</a>
</div>
<div class="clear"></div>
</div>
</div>
</body>
My CSS code is as follows:
* {
border:none;
line-height:normal;
margin:0;
outline:none;
padding:0;
text-decoration:none;
}
body{
background:#70133F;
color:#000000;
font-family:Arial, Verdana, Helvetica, sans-serif;
font-size:12px;
margin:0 auto;
}
.clear{
clear:both;
font-size:0;
height:0;
line-height:0;
margin:0;
padding:0;
}
.content{
background:#FFFFFF;
margin:0 auto;
width:970px;
}
.header{
height:160px;
}
.header #logo{
float:left;
font-size:0;
height:124px;
margin:25px 0 0 18px;
width:204px;
}
.header .util-links {
color:#E83F00;
font:bold 12px;
float:right;
margin:135px 15px 0 0;
text-align:right;
text-transform:uppercase;
}
.header .util-links a {
padding:0 10px;
}
.header .hog {
height:3px;
position:relative;
margin-top:-152px;
text-align:right;
width:945px;
}
.header .hog a.see-holiday {
color:#E83F00;
font:bold 12px;
text-transform:uppercase;
height:40px;
width:254px;
}
.header .hog .guidelines {
display:none;
margin-left:524px;
text-align:left;
width:428px;
}
Thanks for the help. Happy Thanksgiving, everyone!
John
Is there a difference between the
Layout Engines of IE8 on Vista and IE8
on XP?
If I understood it right, it appears that you are not only having 2 servers but you are also accessing the site from 2 different computers, one running XP and another Vista. Open the IE developer tools in both computers and observe the browser mode and document mode. Perhaps one of the browsers has been set permanently to IE7 compatibility mode? Or one of the servers is sending the <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /> tag forcing a compatible mode?
There is a slight difference between IE on XP and Vista because IE uses OS controls to render certain controls such as buttons, textboxes, select boxes and scrollbars. However, the difference in layout caused by that should not be that drastic.
For finding differences in headers, you can install a tool such as fiddler or httpwatch and inspect them in both machines.

Resources