CSS Responsive Grid - items getting stuck on those with longer height - html

I'm building a portion of a portfolio site that displays a 4-column grid with images and their titles using relative units of measurement so that it scales with the browser window's size. Right now it works fine with each .item assigned a property of float:left and max-widths defined as a percentage of the overall #container's width (in this case 1100px or 68.75em). It works fine with the exception of the titles, which go below each image in a span. When one of the titles is longer than the 220px (or 20% of the container) the height increases and the items in the next row will get "stuck" on it.
I can fix this easily using PHP to insert a clear:both div after every 4th div (to effectively make a new "row" in the html) but I plan on using media queries or some other device to reduce the amount of columns to 3, 2 and 1 as the browser window shrinks. It would be easier if I could simply have the rows defined by floating the items. Possible solutions?
Styles:
body {
font-size: 100%;
line-height: 100%; /* Neat */
font-family: Helvetica, Arial, sans-serif;
}
#container {
max-width: 68.75em; /* 1100px */
margin: 40px auto;
border: 1px solid #000;
}
.item {
float: left;
width: 20%;
max-width: 20%;
height: auto;
padding: 2.5%;
background-color: #eee;
}
.item img {
display: block;
width: 100%;
max-width: 100%;
height: auto;
}
.item span {
width: 100%;
max-width: 100%;
margin-top: 1em;
display: block;
text-transform: uppercase;
line-height: 1.5em;
}
HTML:
<div id="container" class="cf"> <!-- "cf" comes from my reset, it's a clear-fix -->
<div class="item">
<img src="images/placeholder.png" height="220" width="220" alt="" title="" />
<span>A Title that is Slightly Longer than the Others</span>
</div>
<div class="item">
<img src="images/placeholder.png" height="220" width="220" alt="" title="" />
<span>A Title</span>
</div>
... (repeat those divs)
</div>

Possible options:
Set the height sufficient to cover two line cases
.grid-item { display: inline-block; vertical-align: top; }
Change the title span to a div, set height and overflow: hidden

I would suggest giving it a short title. If that's not possible, you could try
.item > span{
height: 0;
position: relative;
}
The images will display appropriately, but the too-long titles will display over the image beneath said title. I don't know if this is acceptable for your needs or not, but you may find it useful.

Related

CSS Anchoring Text to Image Corner

I'm trying to make a responsive design were images scales according to the viewport, depending on whichever width or height of the viewport restricts the image, it never exceeds the viewport.
This was quite easy to achieve, but now I have the issue that the left-aligned title over the images doesn't of course follow the center'd image, but instead sticks by the page margin. I tried experimenting with all sorts of different calculated padding and other junk, but so far I can't figure it out.
What I'd ideally would like to do is to scale a box according to the viewport and center-align that box, and then have a full width image inside the box, and the left aligned title above it.
Here's what I've got so far, excuse the crude CSS.
Code:
/* Create 1 column that floats */
.column {
float: center;
width: 100%;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Add a card effect for articles */
.card {
background-color: var(--bg-color);
padding: 1vw;
margin-top: 1vw;
cursor: pointer;
width: 100%;
border-style: none;
}
.card h3 {
color: var(--text-color);
font-family: 'Lato', sans-serif;
font-size: 3vw;
text-align: left;
margin-left: 1.5vw;
margin-bottom: 0vw;
margin-top: 0vw;
}
.card img {
display: block;
width: auto;
height: auto;
max-width: 95vw;
max-height: 75vh;
margin-left: auto;
margin-right: auto;
padding: 1vw;
}
<div class="content">
<a href="page.html"><button type="button" class="card">
<h3>Image Title</h3>
<img src="https://via.placeholder.com/1920x1080.jpg"
alt="Image Title">
</button></a>
</div>
Supposing you can change your HTML structure and you're open to use a more semantic HTML structure you should go with the following.
.card {
display: flex;
justify-content: center;
}
<div class="card" onclick="myFunction()">
<figure>
<figcaption>Caption</figcaption>
<img src="https://dummyimage.com/100/eee">
</figure>
</div>
I've also added the onclick="myFunction()" attribute so you can mimic a button behavour aswell.
You could also use <a> tag instead of the <div> tag, just set it to display:block.
Now a little weird hack
I do not recommend this approach as it is not semantic (you will have to style it on your own).
.figure {
display: flex;
flex-flow: column nowrap;
margin: auto;
}
h3 {
text-align: left;
margin: 0;
}
<button class="figure">
<h3>Caption</h3>
<img src="https://dummyimage.com/100/eee">
</button>
You can use this if you absolutely need to have a <button> tag and you can't change your HTML structure. If none of those apply, the only advantage of this method is that you don't need another wrapper.
Notice that if you change <button> to <div> in the above example it will not work as it relies on the fact that <button> is a replaced element, and so its size is defined by content width, just like inline elements, but its margin are calculated like block elements, so you can use margin:auto.
CSS Spec on 10.3.4:
The used value of 'width' is determined as for inline replaced elements. Then the rules for non-replaced block-level elements are applied to determine the margins.
Anyway, I was just sharing what I've found while looking for how to solve this without changing HTML structure. Please go with the first solution.
You could wrap the h3 and the img in a div and center that. By the way, float:center doesn't exist.

How to align image in horizontal centre of div & set image next to it?

I want to set an image centre of div & just next it want to set a new image in the same line. I don't want to set it in next line.
I have tried below code it set first image in centre but not other image next to it. It put image in next line.
div {
margin: 0 auto;
overflow: auto;
background: #0cf;
}
<div>
<img src="../images/catchBug.png" alt="img1">
<img src="../images/signature.png" alt="img2">
</div>
The easiest way is to give the parent div text-align: center and position: absolute to the bottom img:
div {
/*position: relative; optional, depends on the image/divs size*/
margin: 0 auto;
overflow: auto;
background: #0cf;
text-align: center;
}
.abs {
position: absolute; /*taken out of the normal document flow; will overflow the parent div since its position is commented out, uncomment if you don't want that*/
}
/* addition */
img {vertical-align: bottom} /*removes bottom margin/whitespace*/
<div>
<img src="http://placehold.it/100x100" alt="img1">
<img src="http://placehold.it/125x125" alt="img2" class="abs">
</div>
As long as you don't want flexbox:
If you've got only two pictures in that row and there won't be more you can always hardcode values of width and margin like this (but remember not to use HTML tags in CSS, it's a bad practice):
img{
display: inline-block;
width: __WIDTH_THAT_IS_WIDE_ENOUGH__;
margin: 0 __WIDTH_THAT_FITS__;
}
I hope I got your question needs well. Try this
.main {
/*Introduce a fixed width so that your margin: 0 auto; can be put to work. This will center the div*/
width: 500px;
margin: 0 auto;
overflow: auto;
background-color: #0CF;
}
.main img {
/*Restrict to inline-block for images
because https://stackoverflow.com/questions/2402761/is-img-element-block-level-or-inline-level*/
display: inline-block;
/*Define a width for the images to keep them in the container 500px*/
width: 48%;
}
<div class="main">
<img src='https://images.unsplash.com/45/ZLSw0SXxThSrkXRIiCdT_DSC_0345.jpg?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ&s=2e1f776c8e5286b86dca14edbd302243' alt='' />
<img src='https://images.unsplash.com/photo-1511290156538-08919a92771d?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ&s=e4b4923f61050049c740fde4e35dd168' />
</div>

Firefox: automatic linebreak with a sibling [float: right] element + overflowing text

I have a problem with Firefox on a really specific graphic implementation.
I think you may understand the problem just by testing this fiddle: on firefox you'll see the problem, on any other browser you'll see the expected result (including IE9).
Design I need:
PNG illustration
I have a main block (dashed border) with a fixed width.
There is 2 lines, one above the other, within the main block. The 2 lines must be align on the right of the main block
Each line contains 2 children. The left ones have a dynamic text (gray background), the right ones are optionnals (blue background). The above right one contains an icon (orange) with a fixed width, the bellow right one is a dynamic temperature (with one decimal maximum).
Blocks are separated by a fixed 5px margin.
Texts and icon must be vertically centered.
In any case, the 2 lines need to have the same width: the smaller one takes the width of the bigger one.
If one line (or both) becomes too large for the main block, the left text (gray background) automatically linebreak.
HTML Code:
<div class="main-wrapper">
<div class="container">
<div class="content upper">
<div class="right-block"><!-- This block is optionnal -->
<div class="icon"></div>
</div>
<div class="left-block">
<div class="vertically-centered">
<p>
Some dynamic text
</p>
</div>
</div>
</div>
<div class="content lower">
<div class="right-block"><!-- This block is optionnal -->
<div class="vertically-centered">
<span>
21,5°
</span>
</div>
</div>
<div class="left-block">
<div class="vertically-centered">
<p>
Some other dynamic text
</p>
</div>
</div>
</div>
</div>
</div>
CSS Code:
/* utilities */
.vertically-centered {
display: table;
height: 100%;
width: 100%;
}
.vertically-centered > * {
display: table-cell;
vertical-align: middle;
}
/* custom styles */
.container {
display: inline-block;
float: right;
max-width: 100%;
}
.content {
width: 100%;
margin: 5px 0px;
height: 85px;
}
.right-block, .left-block {
height: 100%;
}
.right-block {
float: right;
font-size: 42px;
margin-left: 5px;
background-color: lightblue;
}
.left-block {
font-size: 25px;
line-height: 25px;
overflow: hidden;
padding: 0 20px;
text-align: left;
background-color: lightgray;
}
.upper .right-block {
width: 85px;
}
.lower .right-block {
padding: 0 15px;
}
.icon {
position: relative;
top: 20%;
left: 20%;
width: 60%;
height: 60%;
background-color: orange;
}
What I already tried:
Put a display: inline-block on the .left-block div, as suggested here, but it doesn't satisfy the need to have the same width on both lines.
Put a display: inline-block on the .content div; makes the line 100% width on other browsers, and create a big right gap within the .left-block on firefox.
Use white-space: nowrap on the .left-block; didn't help.
Make the .left-block div floating (right or left), but it doesn't work if the text is too large for the main container
And a lot of other things but not a single one compatible with all the browsers (Chrome, Firefox, Safari, IE9+, Edge)...
A precision although I don't think it will change anything: it is responsive.
I'm trying something with flexbox but... IE9... If anybody has a suggestion.
You can use the CSS word-break property to allow line breaks in the middle of long words:
.content {
width: 100%;
margin: 5px 0px;
height: 85px;
word-break: break-all;
}
I found out a solution with flexbox!
I added a display: flex to the .content div with flex-direction: row-reserve to keep the order of the element and still be able to use float: right for IE9.
In addition, there is a flex: auto property on .left-block divs to take as much space as possible (Note: IE11 needs flex-basis to be set to be able to calculate the space wanted by the flex-grow property. That's why I used auto instead of 0 on the flex property. See details)
The completed CSS code
.content {
width: 100%;
margin: 5px 0px;
height: 85px;
display: flex; /* Initialize flexbox */
flex-direction: row-reverse; /* keep the order of the element */
border: 1px dashed gray;
}
.left-block {
font-size: 25px;
line-height: 25px;
overflow: hidden;
padding: 0 20px;
text-align: left;
background-color: lightgray;
flex: auto; /* the text blocks take all the available space */
}
Here's the fiddle with the correction. Sometimes IE9 takes 2 lines of text instead of 1 (the text is 2px larger that the container, I don't know why...) but atleast it's readable!

HTML CSS design: div growing in size

Following some instructions given in another question, I've rewritten a web page used to print pdf and to be shown in the web. Here's some code:
/** CSS File **/
body {
background-color: lightcyan;
border: 1px solid black;
font-family: sans-serif;
height: 268mm;
margin-bottom: 13mm;
margin-left: 11mm;
margin-right: 12mm;
margin-top: 10mm;
width: 187mm;
}
img {
margin: 0mm;
padding: 0mm;
max-height: 100%;
max-width: 100%;
}
div.ClrOvFlw, div.Pedice {
clear: both;
overflow: auto;
}
div.Left, div.Left75 {
clear: left;
float: left;
}
div.Right, div.Right25 {
clear: right;
float: right;
}
div.Left75 {
background-color: yellow;
height: 20.74mm;
margin-right: 1mm;
padding: 0mm;
width: 129mm;
}
div.Right25 {
background-color: blue;
height: 20.74mm;
margin-left: 1mm;
padding: 0mm;
width: 51mm;
}
<!-- HTML -->
<body>
<div class="ClrOvFlw">
<div class="Left75">
<img id="Logo" src="../Box Logo Testata/Logo.jpg" alt="Mark">
</div>
<div class="Right25">
<div id="Bandiera">
<img id="BandieraImg" src="" alt="ITA">
</div>
<div id="MadeInItaly">
MADE IN ITALY
</div>
</div>
</div>
</body>
As you can see, I've calculated the dimensions on a given template. If I don't put srcs in the img tags everything is fine, but when I put them on, the Right25 div flows on another row because the Left75 div becomes bigger. Here's a link to fiddle.
What am I missing?
EDIT
Here's the image you requested.
The problem isn't that the left element is increasing in size, it's that the right element is being pushed in from the right side of the screen. Why? because the css is making room for a scrollbar, and your width values are all fixed length.
It's being caused by the overflow: auto CSS being applied to div.ClrOvFlw here:
div.ClrOvFlw, div.Pedice {
clear: both;
overflow: auto;
}
For some reason, when you add an image to the src, the CSS is expecting the requirement of a scrollbar - Can't say for sure, but I would imagine it has to do with the size of the image before the constraints of the div it is being put into are applied. If the resolution of the image is large enough that - were it not shrunk to fit inside the div - it would require an overflow to be seen. You can test this by putting an image that is naturally small in as the src instead, like http://www.w3schools.com/tags/smiley.gif. Note that the divs fit as expected when this is your source.
Your solution is either remove the overflow: auto from the ClrOvFlw div, or resize your source image so that its natural resolution is small enough that it would fit within the prescribed height of the containing div.
Note: the fixed length stuff is an issue because the containers can't respond to the reduced space - 25% of the containing div is no longer 51mm. You could try using % widths instead if that is an option - it may also alleviate the issue without having to redo your image.

HTML/CSS - How can I change the spacing or add whitespace so the boxes are equal?

I'm new to the frontend and work out of the backend. I found a layout I am interested in using however noticed that when typing in these boxes if the text length isn't equal the sizing of the box changes for one of the boxes in the row and not all.
I want them all the be sized equally so if one box is using one line of text and the others two lines, the one line provide white space to match the size.
E.g.
I'd like all the boxes on that row to add in the whitespace so the boxes are equal in size so I don't get the layout issues since in the pic above.
Like this:
How do I change the css for the boxes to automatically resize all the boxes and not just one?
This is the layout I am using: http://adapt-trackers.blogspot.in/
It seems as though right now their spacing is determined by the margin/padding/border values. Try setting a height and width so that they are all the same.
For example:
#selectable li { margin: 3px; padding: 1px; float: left; width: 165px; height: 160px; font-size: 1.5em; text-align: center; }
try this (courtesy of CSS the Missing Manual):
<div id="gallery">
<div class="figure">
<div class="photo">
<img src="../images/carpet.jpg" alt="Carpet Grass" width="200" height="200" /> </div>
<p>Figure 1: Even the carpet-like <em>Carpetorium Pratensis</em> requires mowing. </p>
</div>
In this example, the gallery div wraps all the images together; the photo class wraps each image and caption together. Here's the CSS:
.figure {
float: left;
width: 210px;
margin: 0 10px 10px 10px;
}
.photo {
background: url(drop_shadow.gif) no-repeat right bottom;
}
.photo img {
border: 1px solid #666;
background-color: #FFF;
padding: 4px;
position: relative;
top: -5px;
left:-5px;
}
.figure p {
font: 1.1em/normal Arial, Helvetica, sans-serif;
text-align: center;
margin: 10px 0 0 0;
height: 5em;
}
Also, there's several gallery frameworks that you could use instead. Or stag some code from dynamicdrive.com
I'd give your tag for ... a minimum height.
add class to your anchor tags:
Link:
...
css:
.link-title{
min-height: 150px;
}