Flex first child 100% width without increasing the width of the container - css

I have a flexbox element and I want the first child to be 100% width, which is working fine, however this has led to an unintended consequence which is that the width of the flex container is still taking up the width that it would be if the first child was not 100% width.
.flex {
display:inline-flex;
flex-wrap:wrap;
border:1px solid black;
}
.first-child {
display:inline-block;
width:100%;
padding:10px 0;
}
.image {
margin-left:5px;
}
.image:nth-child(2) {
margin-left:0;
}
img {
display:block;
}
<div class="flex">
<span class="first-child">Lorem Ipsum</span>
<div class="image">
<img src="https://i.picsum.photos/id/54/300/300.jpg?hmac=LmoFB-1252dfBUuC19mSt9fePqp2CCJEY2_EL9ewdPE" />
</div>
<div class="image">
<img src="https://i.picsum.photos/id/916/300/300.jpg?hmac=lP6QL2bac_8f8XYGAVNzgf2nHPlfRUNDAiDM-Kejgpg" />
</div>
I have added a border to the container to demonstrate how it is wider than I expect. How can I go about making sure the first child is on it's own line with 100% width while still having the border end right at the right side of the second image?
Current result:

Use CSS grid for this:
.grid {
display: inline-grid;
gap: 5px;
border: 1px solid black;
}
.first-child {
padding: 10px 0;
grid-column: span 2; /* update this to the number of images*/
}
img {
display: block;
}
<div class="grid">
<span class="first-child">Lorem Ipsum</span>
<div class="image">
<img src="https://i.picsum.photos/id/54/300/300.jpg?hmac=LmoFB-1252dfBUuC19mSt9fePqp2CCJEY2_EL9ewdPE" />
</div>
<div class="image">
<img src="https://i.picsum.photos/id/916/300/300.jpg?hmac=lP6QL2bac_8f8XYGAVNzgf2nHPlfRUNDAiDM-Kejgpg" />
</div>

Related

Expand div when divs nested inside overflow

I am trying to figure out how to expand a div when the children contain divs that overflow (to show overlapping images);
div.container {
position:relative
}
div.column {
display: inline-block; // in my case I want to avoid wrapping
width: 180px;
}
div.item-contains-long-image {
display: block;
height: 25px;
overflow: visible;
position: relative;
}
I would like the container to expand vertically to contain the images overflowing from the inner div. I could add padding to the bottom of the div equivalent to the image height, but am looking for a better way.
#Teobis i took your answer as base for a flex example, hope you dont mind :)
div.container { /* this has been rewritten */
display: flex;
flex-direction: row;
}
div.column {
border:1px solid blue; /*just to show the size*/
display: inline-block; /* in my case I want to avoid wrapping */
width: 180px;
vertical-align:top;
}
div.item-contains-long-image {
display: inline-block;
height: 25px;
/* overflow: visible; no needed, default property*/
position: relative;
}
<div class="container">
<div class="column">
<div class="item-contains-long-image">
<img src="http://via.placeholder.com/180x270">
</div>
</div>
<div class="column">
<div class="item-contains-long-image">
<img src="http://via.placeholder.com/180x310">
</div>
</div>
<div class="column">
<div class="item-contains-long-image">
<img src="http://via.placeholder.com/180x110">
</div>
</div>
</div>
Is this structure what you are looking for??
First of all, you need white-space:nowrap; on the parent of display: inline-block;
or you could use flexbox;
div.container {
position:relative;
border:1px solid red; /*just to show the size*/
white-space:nowrap; /*Necesary for no wrap on .column*/
min-height:150px; /* minimum height */
}
div.column {
border:1px solid blue; /*just to show the size*/
display: inline-block; /* in my case I want to avoid wrapping */
width: 180px;
vertical-align:top;
}
div.item-contains-long-image {
display: inline-block;
height: 25px;
/* overflow: visible; no needed, default property*/
position: relative;
}
<div class="container">
<div class="column">
<div class="item-contains-long-image">
<img src="http://via.placeholder.com/180x270">
</div>
</div>
<div class="column">
<div class="item-contains-long-image">
<img src="http://via.placeholder.com/180x310">
</div>
</div>
<div class="column">
<div class="item-contains-long-image">
<img src="http://via.placeholder.com/180x110">
</div>
</div>
</div>
Hope this helps

How do I display text inline with an image?

I have an image which is on the right and the text needs to be beside it on the left with the start of the text inline with the top of the image, how would I do this?
#pic0 {
width:100%;
}
#pic0img {
display: inline-block;
height: auto;
margin-left:50%;
width:100%;
margin-bottom:5px;
}
pic0txt {
margin-right:52%;
width:48%;
}
<div id="pic0">
<div id="pic0img">
<img src="Images/Activities/pic0.fw.png" width="50%"
onmouseover="this.src='Images/Activities/pic0.fw.png'"
onmouseout="this.src='Images/Activities/pic0.fw.png'" />
</div>
<div id="pic0txt">
<p>test</p>
</div>
</div>
See this simplified snippet (remove borders which are just for test):
#pic0txt {
display: inline-block; border:1px solid red;
text-align:center;
vertical-align:top;
width:48%;
}
#pic0img {
display: inline-block; border:1px solid red;
width:48%;
}
<div>
<div id="pic0txt">test</div>
<img id="pic0img" src="https://www-asp.azureedge.net/v-2016-11-01-012/images/ui/home-free-courses.png" />
</div>
<hr/>
<div>
<img id="pic0img" src="https://www-asp.azureedge.net/v-2016-11-01-012/images/ui/home-free-courses.png" />
<div id="pic0txt">test</div>
</div>
Use flex on the parent, then flex-grow on each flex item so they'll be 50% width, and set the image to width: 100% so it fills it's parent.
.flex {
display: flex;
}
.flex > div {
flex-grow: 1;
flex-basis: 0;
}
img {
width: 100%;
}
<div class="flex">
<div>
<p>text</p>
</div>
<div>
<img src="http://www.w3schools.com/css/paris.jpg">
</div>
</div>
Try this simple and easy trick:
<div id="pic0">
<div id="pic0img">
<p> <img src="http://images5.fanpop.com/image/photos/31300000/beautiful-heart-pic-beautiful-pictures-31395948-333-500.jpg" width="50%"
onmouseover="this.src='Images/Activities/pic0.fw.png'"
onmouseout="this.src='Images/Activities/pic0.fw.png'" />test</p>
</div>
</div>
#pic0 {
width:20%;
}
#pic0img {
display: inline-block;
height: auto;
margin-left:50%;
width:100%;
margin-bottom:5px;
}

Select last sibling in each group of siblings

So I want to select the last sibling in a group of elements, but there are more than one group in the parent container.
<div class="wrapper">
<div class="select"></div><!-- padding-top -->
<div class="select"></div>
<div class="select"></div><!-- padding-bottom -->
<p>Some text</p>
<div class="select"></div><!-- padding-top -->
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div><!-- padding-bottom -->
<div>
So in this case, for every clump of .select elements, I need to add padding-top to the first one and padding-bottom to the last one. The tricky part is that the clump of .select elements can be infinitely large/small, but the first and last elements need padding.
This example works for the top padding...
// add padding-top to all elements
.select {
padding-top: 1em;
}
// remove it for general direct siblings
.select + .select {
padding-top: 0;
}
// this will only add to the last .select in the parent container,
// not the last in each clump of .select elements
.select + .select:last-of-type {
padding-bottom: 1em;
}
But the bottom padding for the last element in the clump is what I'm having issues with.
I can't add wrapper elements because this is pseudo generated code. JS would also make this a fairly straightforward solution, but I'd rather exhaust all of my CSS only solutions first.
Edit: The HTML structure is 100% arbitrary as it will be generated by the user in a WYSIWYG. However, there will be some sections of .select elements next to each other.
.wrapper>*:not(.select) + .select, .wrapper>.select + *:not(.select) {
margin-top: 1em;
}
.wrapper>.select:last-child {
margin-bottom: 1em;
}
If positioning was not the issue, and setting a margin-top on the next element doesn't do it (for example you have a background on .select and you actually need bottom padding on the last item in the group), well... you can't select the previous sibling with CSS.
So here's a solution using jQuery:
$('.wrapper>*:not(.select)').each(function() {
$(this).prev(".select").css({
'padding-bottom': '20px'
})
})
body {
margin: 0;
}
.wrapper {
padding: 20px;
}
.select {
background-color: #eee;
border-bottom: 1px solid white;
}
/* ignore CSS above, it's for coloring and padding so you see elements */
.select {
padding-top: 20px;
}
.select ~ .select {
padding-top: 0;
}
*:not(.select) + .select {
padding-top: 20px;
}
.wrapper>.select:last-child {
padding-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="select">select</div>
<!-- padding-top -->
<div class="select">select</div>
<div class="select">select</div>
<!-- padding-bottom -->
<p>Some text</p>
<div class="select">select</div>
<!-- padding-top -->
<div class="select">select</div>
<div class="select">select</div>
<div class="select">select</div>
<div class="select">select</div>
<!-- padding-bottom -->
</div>
Old question, I know, but I just had the same problem so thought this might be helpful for someone. Using :not() worked for me; I used borders instead of paddings for the example so it's more visible.
.wrapper * {
margin: 0;
padding: 0;
}
.select {
border-top: 30px solid #f00;
}
.select:last-of-type {
border-bottom: 30px solid #f00;
}
.select + .select {
border-top: 0;
}
.select + :not(.select) {
border-top: 30px solid #f00;
}
<div class="wrapper">
<div class="select">Select 1</div><!-- padding-top -->
<div class="select">Select 2</div>
<div class="select">Select 3</div><!-- padding-bottom -->
<p>Some text</p>
<div class="select">Select 4</div><!-- padding-top -->
<div class="select">Select 5</div>
<div class="select">Select 6</div>
<div class="select">Select 7</div>
<div class="select">Select 8</div><!-- padding-bottom -->
<div>
Is the structure always 2 groups of div separated by a p?
And is the padding meant to create space at top/bottom of each group?
And if so, would margin be okay instead?
Then here is a sample doing like so.
.wrapper div:first-child,
.wrapper p {
margin-top: 20px;
}
.wrapper div:last-child,
.wrapper p {
margin-bottom: 20px;
}
/* just for coloring making it visible */
.wrapper {
background-color: #666;
border: 1px solid black;
}
.wrapper p,
.select {
background-color: #aaa;
border: 1px solid white;
}
<div class="wrapper">
<div class="select">1</div><!-- padding-top -->
<div class="select">2</div>
<div class="select">3</div><!-- padding-bottom -->
<p>Some text</p>
<div class="select">1</div><!-- padding-top -->
<div class="select">2</div>
<div class="select">3</div>
<div class="select">4</div>
<div class="select">5</div><!-- padding-bottom -->
<div>
If it needs to be padding and you don't want to use script, this might work.
.wrapper div:first-child {
padding-top: 20px;
}
.wrapper div:last-of-type {
padding-bottom: 20px;
}
/* just for coloring making it visible */
.wrapper {
border: 1px solid black;
background-color: #666;
}
.wrapper p,
.select {
background-color: #aaa;
border: 1px solid white;
}
<div class="wrapper">
<div class="select">1</div>
<div class="select">2</div>
<div class="select">3</div>
<p>Some text</p>
</div>
<div class="wrapper">
<div class="select">1</div>
<div class="select">2</div>
<div class="select">3</div>
<div class="select">4</div>
<div class="select">5</div>
</div>
I don't think you need to touch the .select elements, just add padding top and bottom to the .wrapper, and margins top and bottom to the p

centering and spacing images in an unknown size parent container

What I am trying to do is centre the img elements both vertically and horizontally inside the img-container. The img-container needs to be a % of the parent element not a fixed width. (ie the outer-container may not always be 1000px)
Although the code below centres the image fine withing the img-container, the width of the img-continer seems to ignore the CSS width 20%. Ie I cannnot get the img-container to get the correct (in this case 200px) width.
Any suggestions?
-Matt.
Here is my CSS
#outer-container{
width:1000px;
}
.img-container {
height:20vh;
width:20%;
vertical-align:middle;
display: table-cell;
}
.centred-img {
display:block;
margin-left:auto;
margin-right:auto;
max-height:100%;
max-width:100%;
}
Here is my HTML:
<div id="outer-container">
<div class="img-container">
<img class="centred-img" src="1.jpg">
</div>
<div class="img-container">
<img class="centred-img" src="2.jpg">
</div>
<div class="img-container">
<img class="centred-img" src="3.jpg">
</div>
<div class="img-container">
<img class="centred-img" src="4.jpg">
</div>
</div>
Use display:inline-block on the child elements and use text-align:center on the parent.
That should do the trick for horizontal centring. To make it centre vertically, you need to
add line-height to your images parent and vertical-align:middle to image itself.
Try using this CSS.
#outer-container{
width:500px;
border:1px solid black;
}
.img-container {
height:20vh;
width:20%;
display: inline-block;
border:1px solid black;
line-height:20vh;
text-align: center;
}
.centred-img {
vertical-align:middle;
margin-left:auto;
margin-right:auto;
max-height:100%;
max-width:100%;
}
Here's my fiddle just using css tables. Is this what you're looking for? The height and width are both dynamic.
http://jsfiddle.net/sinnix/dpppzuds/
<div class="container">
<div class="row">
<div class="cell">
<img src="http://placehold.it/50">
</div>
<div class="cell">
<img src="http://placehold.it/50">
</div>
<div class="cell">
<img src="http://placehold.it/50">
</div>
<div class="cell">
<img src="http://placehold.it/50">
</div>
</div>
</div>
.container {
display: table;
width: 90%; /* adjust as desired */
height: 100px;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
width: 25%;
background: magenta;
vertical-align: middle;
text-align: center;
}
.cell:nth-child(even){
background: yellow;
}

How to align multiple divs in another?

So here's my HTML:
...
<div class="header">
<div class="left">
</div>
<div class="center">
<img class="logo" src="linktomyimage.com/image.png" />
</div>
<div class="right">
</div>
</div>
<!-- And the desired result is: -->
[ [LEFT] [CENTER] [RIGHT] ]
The only CSS I have is:
* {
margin: 0px;
}
img.logo {
display: block; margin-left: auto; margin-right: auto;
}
I really need help to align the three divs on the whole page. Also div.center must have the same size as the image, aka width - 800px and height - 600px.
It looks much more like a table than divisions to me...
<table class="header"><tr>
<td class="left"></td>
<td class="center">
<img class="logo" src="linktomyimage.com/image.png" />
</td>
<td class="right"></td>
</tr></table>
Think about so CSS afterwards :
table.header{
width: 100%;
border-collapse: collapse;
}
table.header td{
vertical-align: top;
border: 1px solid #404040;
}
table.header td.center{
width: 800px;
height: 600px;
}
This is just a code sample, get the idea, and adapt to your own needs ^^
Add these classes to your css
.left
{
display:inline-block;
width:25%;
}
.center
{
display:inline-block;
width:50%;
}
.right
{
display:inline-block;
width:25%;
}
With the following markup, 2 solutions come to mind:
MARKUP
<div class="header">
<div class="left">
Some left test
</div>
<div class="center">
<img class="logo" src="http://placehold.it/50x50" />
</div>
<div class="right">
Some right text
</div>
</div>
Solution #1
Float left and right sides and use display-block on the center
FIDDLE
Css
.header
{
text-align: center;
width:100%;
}
.left
{
float:left
}
.right
{
float:right;
}
.center
{
display:inline-block;
}
Solution #2
Use text-align: justify; on the header element.
Then stretch the content to take up 100% width
FIDDLE
CSS
.header
{
text-align: justify;
width:100%;
}
.header > div
{
display: inline-block;
}
.header:after {
content: '';
display: inline-block;
width: 100%;
}
.left, .centre, .right {
float:left;
}
What float:left does is, is it'll make each container organize itself from the left, so you get:
[LEFT]-[CENTRE]-[RIGHT]

Resources