Responsive image with floated and full width layout - css

I'm working on a responsive layout. See this fiddle, or code below, for an example: http://jsfiddle.net/jasonpalter/GBygZ/
The image has a left margin -- necessary in when it's not spanning the full width of the its container. But when the image spans the full width of the container, the left margin needs to be removed. We can accomplish this simply with a breakpoint, but the image itself if dynamic, and we don't know what its dimensions will be.
Is there an automatic way (CSS, or less preferably javascript) to ensure that the image padding can disappear when the image spans the full width of its container?
HMTL
<div class="pod">
<div class="img-right">
<img src="http://placehold.it/460x220" width="460" height="220" />
</div>
<h3>Lorem Ipsum</h3>
<div>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
<p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>
</div>
</div>
CSS
.pod {
overflow: hidden;
padding: 5px;
border: 1px dotted #ccc;
font-family: Arial, sans-serif;
font-size: 12px;
line-height: 1.4;
}
.img-right {
float: right;
}
.img-right img {
box-sizing: border-box;
padding: 0 0 0 5px;
max-width: 100%;
height: auto;
}

To do this in javascript, you would need to create an Image object, set its src attribute to the image source, and then pass a function that grabs the images dimensions to the image object's onload attribute. With that information, you could bind a function to the window's resize event that strips the image's padding when the image spans the full width of the container and reinstates it when the opposite happens.
There is unfortunately no way to do this in CSS, though being able to just write a img:not(:resized) selector would be nice!

In my ecperience this would not be possible without knowing the width of the image, in CSS alone. A jQuery solution would be very simple
DEMO http://jsfiddle.net/kevinPHPkevin/GBygZ/5/
var windowWidth = $(window).width();
if ($('#image').width() < windowWidth) {
$('#image').css('padding-left', '10px')
}
When you test this in a fiddle it will not work as the window is the browser window width, not the width of the editable column that is assigned to the fiddle.

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.

Left align div to centered container

I have a container centered with a max width as follow:
#container {
margin-left: auto;
margin-right: auto;
max-width: 900px;
}
Now I want to create a new div just below the contained one, but I want this new div to align to the left and expand beyond the right side of the container. Something like that:
|||||||||||||||||||||||||||||||||||| #container
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| #div 2
The difficulty is that #container margins are auto, so how can I force #div to follow #container left margin as the browser resizes?!
NOTE: I am looking for a pure CSS solution WITHOUT JAVASCRIPT
EDIT: It was not clear in my explanation but, my goal was to make the #div ADJACENT to the #container. Like this:
<div id="container"></div>
<div id="div"></div>
I ended up refactoring my html to use #bananabran solution with absolute positioning which simply uses parent-child structure:
<div id="container">
<div id="div"></div>
</div>
You don't have to force the div to follow its container's left margin. Divs naturally start at the top-left of their container (unless otherwise specified or affected by). You also do not need to use Grid or FlexBox. CSS3, and even CSS2 can do this natively.
See working CodePen example: https://codepen.io/bananabrann/pen/QWWdXQZ
Assuming you have no other code affecting your code...
<div id="container" />
<div id="my-div" />
#container {
background-color: blue;
position: relative;
margin: 0 auto;
width: 900px;
height: 300px;
}
#my-div {
background-color: red;
position: absolute;
bottom: 0;
width: 500px;
height: 20px;
}
CSS-Grid can do that:
.wrap {
display: grid;
grid-template-columns: 1fr minmax(auto, 400px) 1fr;
/* 400px for demo purposes */
}
.container {
padding: 1em;
background: pink;
grid-column-start: 2;
}
.wide-r {
padding: 1em;
background: lightgreen;
grid-column: 2 / span 2;
}
<div class="wrap">
<div class="container">Container
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates, similique, maxime aspernatur dolorum quod recusandae possimus fuga blanditiis laudantium delectus quis magni. Veniam, consequuntur dolores facilis cupiditate fugiat ullam aspernatur!
Corporis excepturi quos esse voluptatem voluptatibus corrupti ea, tempora culpa magni, hic aspernatur pariatur molestias itaque doloremque assumenda ad fugiat!</p>
</div>
<div class="wide-r">Wide Right</div>
</div>

Prevent "fragmentation" of wrapped text next to floated image

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>

two scrollbars on centrally divided layout

I am trying to build a centrally divided layout using bootstrap.
the left side of the screen should be fixed and the right side of the screen should be scrollable.
It works fine so far, but when I test the layout on small devices, the right part of the screen gets two scrollbars.
When I hide the scrollbar on small devices, the content on the right side is not scrollable any more.
changing overflow:auto; to overflow:visible; solves the problem with two scrollbars, but the left side of the screen is not fixed any more and scrolls with the right side.
position:fixed; doesn't solve the problem.
here is the code:
.lw { font-size: 60px; }
body {
margin: 0;
}
#left {
background-color: yellow;
height: 100%;
overflow: hidden;
}
#right {
background-color: pink;
height: 100%;
overflow: auto;
text-align: center;
font-size: 8vw;
}
.container_left {
padding-top: 10%;
padding-bottom: 10%;
}
#question {
text-align: center;
font-size: 4vw;
padding-bottom: 50px;
}
#tip {
text-align: center;
}
#media screen and (max-width: 768px) {
#right{
overflow: hidden;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-6" id="left">
<div class="container_left">
<p id="question">Lorem ipsum dolor sit amet</p>
<p id="tip">tip</p>
</div>
</div>
<div class="col-lg-6" id="right">
<p style="color:red">start</p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
<p style="color:red">end</p>
</div>
</div>
</div>
</body>
</html>
I would appreciate your advice.
best regards
Apply this css to hide the scrollbar in your second block. This will hide the scrollbar in that individual element but keep the site's main scrollbar:
#element::-webkit-scrollbar {
display: none;
}
Note that this won't have full browser support.
Another, better solution would be to rework your html/css in general so that the first block is set in a fixed position while the remainder of the page scrolls as normal. This will have wider support across platforms. This way you're not fiddling with scroll bars.

how to vertically align text next to a floated image?

I want to vertically align a span after a floated image.
I searched for it in stack overflow and find this post. but my image is floated.
<div>
<img style="width:30px;height:30px; float:left">
<span style="vertical-align:middle">Doesn't work.</span>
</div>
I give vertical-align:middle to image and nothing change!
Thanks
Even though this is an extremely old post, you can achieve this using Flexbox:
div {
display: flex;
align-items: center;
}
<div>
<img style="width:30px;height:30px;" src="http://lorempixel.com/output/abstract-q-c-640-480-8.jpg" />
<span>Doesn't work.</span>
</div>
JsFiddle example
First remove float from it. Write like this:
<img style="width:30px;height:30px;vertical-align:middle" src="http://lorempixel.com/output/abstract-q-c-640-480-8.jpg">
<span>Doesn't work.</span>
Check this http://jsfiddle.net/ws3Uf/
Add line-height (equal to picture height):
<div>
<img style="width:30px;height:30px; float:left">
<span style="vertical-align:middle; line-height: 30px;">Works!</span>
</div>
See example.
You can manually change as well
<div>
<img style="width:30px;height:30px float:left">
<span style="float:left;padding-top:15px;">Will work.</span>
</div>
Demo
Or you can use a table
A <span> is an inline element, try adding display:block to the span, give it the same height as the image and a line height to match. Float it left as well. That should work
You could do the following:
div:after {
content:"";
clear:both;
display:block;
}
float the picture
set a height to picture.
put a div1>div2>text after the picture.
set div1 the same height as the picture.
set div2 position relative, top 0 and transform translateY -50.
https://codepen.io/aungthihaaung/pen/ExXGvGy
.picture {
height: 300px;
float: left;
}
.div1 {
height: 300px;
}
.div2 {
position: relative;
top: 50%;
transform: translateY(-50%);
}
<img src="https://via.placeholder.com/300" class="picture" />
<div class="div1">
<div class="div2">
<h1>Hi There!</h1>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Et, deleniti
perferendis! Ut, eaque iste incidunt atque perferendis odio laborum
nobis obcaecati exercitationem molestiae nihil est recusandae
mollitia. Fuga beatae inventore, adipisci ipsa aliquid corporis harum
ex tenetur iure assumenda optio quod eaque omnis porro ab consequuntur
unde a totam minima.
</div>
</div>

Resources