dadoo
dadoo

Reputation: 21

How to make a div adapt to its content's width?

this is my first question here, but I've read many Java answers which helped me a lot. I did some research before, but don't hesitate to tell me if I duplicated a question or am doing anything wrong.

I'm trying to create a thumbnails gallery and I made a jsfiddle here.

HTML

<body>
  <div id="main">
    <div id="wrapper">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>
  </div>
</body>

CSS

#main {
  background-color: rgba(255, 105, 180, 0.5);
  height: 100vh;
  padding: 10px;
}

#wrapper {
  background-color: blue;
  display: inline-block;
  padding: 5px;
}

.box {
  display: inline-block;
  background-color: red;
  width: 200px;
  height: 200px;
  margin: 5px;
}

I would like to center the red boxes in the main div, but not like text-align: center;, align the boxes left-to-right between them, and center the whole block. So I thought, why not make a wrapper div and center it ? This is where my problem is, I would like the blue wrapper to be no larger than its content, but it fills the main div. An answer here says inline-block should solve the issue but I can't figure out how. The whole thing surely can be made quite easily, so what am I missing ?

If TLDR, I made some snapshots here : https://i.sstatic.net/JZzyW.jpg

Thanks a lot !

Upvotes: 2

Views: 1922

Answers (3)

zer00ne
zer00ne

Reputation: 44086

Use flexbox. This is the heart of the design:

#wrapper {
  background-color: blue;
  height: auto;
  padding: 10px;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-content: space-between;
  flex-wrap: wrap;
}

Added 2 invisible boxes at the bottom to push the last red box to the left.

FIDDLE

SNIPPET

html,
body {
  width: 100%;
  height: 100%;
}
#main {
  width: 100vw;
  max-width: 640px;
  height: auto;
  background-color: rgba(255, 105, 180, 0.5);
  padding: 10px;
}
#wrapper {
  background-color: blue;
  height: auto;
  padding: 10px;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-content: space-between;
  flex-wrap: wrap;
}
.box {
  display: block;
  background-color: red;
  margin: 2.5px auto 10px;
  width: 200px;
  height: 200px;
}
.space {
  background: none;
}
<body>
  <div id="main">
    <div id="wrapper">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="space box"></div>
      <div class="space box"></div>

    </div>
  </div>
</body>

Upvotes: 0

ChrisM
ChrisM

Reputation: 1673

So the reason why your content is expanding to fit 100% of the space available is that as the boxes are 'inline-block' they are situated within a line (think line of text) that will take up 100% of the width if it wraps. The browser doesn't know your intention and treats this exactly like text which, normally, we would want to behave like this.

In order to change this we will need to either :

  1. Specify the maximum width of the container.
  2. Specify the number of elements that can be contained on one line before wrapping.

Either way we do have to hardcode some assumptions/limitations (without involving any script or complex media queries etc).

Specifying the maximum width of the wrapper is probably the most straightforward way - like this:

body{
  width:100%;
}

#main {
  background-color: rgba(255, 105, 180, 0.5);
  height: 100%;
  padding: 10px;
  width:100%;
}

#wrapper {
  background-color: blue;
  display: block;
  padding: 5px;
  max-width:640px;
  margin: 0 auto;
}

.box {
  display: inline-block;
  background-color: red;
  width: 200px;
  /* If you want it to shrink rather than wrap you could say
  width: calc((100% / 3) - 15px);*/
  height: 200px;
  margin: 5px;
}

JS Fiddle: https://jsfiddle.net/Chipmo/z30fLv0v/


Specifying the number of elements before wrap is a bit more tricky. The solution I have found is to add <br> tags after each box and then selectively activate them using the nth-child selector. I'm sure there'll be a way of doing this which doesn't involve extraneous tags - perhaps with display: table shenanigans or flexbox, but this works and shows the basic concept.

JS Fiddle: https://jsfiddle.net/Chipmo/xsf6c7e5/


SO snippets below:

Max-width

body{
  width:100%;
}

#main {
  background-color: rgba(255, 105, 180, 0.5);
  height: 100%;
  padding: 10px;
  width:100%;
}

#wrapper {
  background-color: blue;
  display: block;
  padding: 5px;
  max-width:640px;
  margin: 0 auto;
}

.box {
  display: inline-block;
  background-color: red;
  width: 200px;
  /* If you want it to shrink rather than wrap you could say
  width: calc((100% / 3) - 15px);*/
  height: 200px;
  margin: 5px;
}
<body>
  <div id="main">
    <div id="wrapper">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>
  </div>
</body>

Number of elements

#main {
  background-color: rgba(255, 105, 180, 0.5);
  height: 100%;
  padding: 10px;
  text-align: center;
}
/*needs 2 ID's to gain higher precedence than the text-align center from above */

#main #wrapper {
  background-color: blue;
  display: inline-block;
  padding: 5px;
  text-align: left;
}
.box {
  display: inline-block;
  background-color: red;
  width: 200px;
  height: 200px;
  margin: 5px;
}
#wrapper br {
  display: none;
}

/*change to 8n for every fourth, 4n for every 2nd etc etc 
  You will probably want to use media queries with this */

#wrapper br:nth-child(4n) {
  display: block;
}
<body>
  <div id="main">
    <div id="wrapper">
      <div class="box"></div><br>
      <div class="box"></div><br>
      <div class="box"></div><br>
      <div class="box"></div><br>
      <div class="box"></div><br>
      <div class="box"></div><br>
      <div class="box"></div><br>
    </div>
  </div>
</body>

Upvotes: 0

br3t
br3t

Reputation: 1658

You can solve it via CSS, but in this way you should write a lot of mediaqueries with hardcoded values. I recommend you do this magic with javascript:

1) Get available width

2) Calculate, how many blocks in one row can appear

3) Get required width and set it for wrapper-container

Upvotes: 2

Related Questions