xxkaiwaxx xxkaiwaxx - 5 months ago 20
CSS Question

Do inline-block elements widths get set by their content?

Hi i just started trying to teach myself HTML/CSS a few days ago. I really dont like asking for answers id rather figure it out myself. But now i need some help so i can find peace and FINALLY move on. Im trying to make a horizontal menu with one drop down button and links in it.



.container {border:1px solid black;
text-align:left;
border-radius:10px;
overflow:hidden;}

.container a {padding:15px;
display:inline-block;
font-size:30px;
text-decoration:none;
background-color:grey;
color:white;}

.aboutcontainer {display:inline-block;}

.about {position:absolute;
display:none;
width:100%;}

.about a {display:block;
text-align:left;
font-size:20px;
padding:15px 5px;}


.aboutcontainer:hover .about {display:block;}

.container a:hover, .aboutcontainer:hover .button {background-color:red;}

.about a:hover {background-color:lightgrey;}

<div class="container">
<a href="#">Home</a
><a href="#">Media</a
><a href="#">Store</a
><div class="aboutcontainer">
<a class="button" href="#">About</a>
<div class="about">
<a href="#">About2</a>
<a href="#">About3</a>
</div>
</div>

</div>





I cant figure out how to make the dropdown menu automatically the same width as the drop down button. I figured that perhaps the drop down menu (.about) which has a width:100% would stretch as far as the div its contained in (.aboutcontainer) which is displayed as inline-block whose width would be determined by the "About" text-link inside of it. But the drop down menu, when displayed, goes the full length of the screen. So it seems to be the case that actual content inside an inline:block element will not define the width of that element. And although the border of an inline:block element wraps around its content automatically, its just an illusion and its actual width is really the full length of the screen, if no fixed widths have been defined in any of the parent divs (hope im using the right terminology). So is there a way to do this without any fixed widths assigned? If not then thats ok. Ill finally have my answer and know what im trying to do is impossible and stop wasting time on it.

Answer

Yes, an inline-block element will size to fit it's content.

Why isn't it working in your situation? You have .about positioned absolute.

When you position an element absolutely, you are taking it out of the HTML structure, meaning:

Do not leave space for the element. Instead, position it at a specified position relative to its closest positioned ancestor if any, or otherwise relative to the containing block. Absolutely positioned boxes can have margins, and they do not collapse with any other margins.
MDN Docs

This means the element is pulled out of the structure, and no longer influences the surrounding elements, or its parent.

An example of this:

.parent {
  background: blue;
}
.child {
  background: red;
  position: absolute;
  top: 20px;
}
Below is the parent element, with a blue background.
<div class="parent">
  <div class="child">Bye bye parent</div>
</div>

If you run the snippet above, you don't see the parent or it's blue background at all, because the child element has been positioned out of it, and relative to the viewport.

Now back to your problem. How can we make the absolute positioned element be positioned relative to its parent, instead of the viewport?

The answer is extremely simple: position:relative; on the parent:

This keyword lays out all elements as though the element were not positioned, and then adjust the element's position, without changing layout (and thus leaving a gap for the element where it would have been had it not been positioned). The effect of position:relative on table-*-group, table-row, table-column, table-cell, and table-caption elements is undefined.

Relative positioning means that the absolute child elements will be positioned relative to the parent. While absolute will still pull the element out of the HTML structure, and it still won't influence the surrounding elements or its parent, the absolute element will now be influenced by its parent. So, in your case, setting width to 100% will be 100% of .aboutcontainers width, instead of 100% of the viewports width:

.container {
  border: 1px solid black;
  text-align: left;
  border-radius: 10px;
}
.container a {
  padding: 15px;
  display: inline-block;
  font-size: 30px;
  text-decoration: none;
  background-color: grey;
  color: white;
}
.container>a:first-of-type {
  border-radius: 10px 0 0 10px;
}
.aboutcontainer {
  display: inline-block;
  position: relative;
}
.about {
  position: absolute;
  display: none;
  width: 100%;
}
.about a {
  display: block;
  text-align: left;
  font-size: 20px;
  padding: 15px 5px;
}
.aboutcontainer:hover .about {
  display: block;
}
.container a:hover,
.aboutcontainer:hover .button {
  background-color: red;
}
.about a:hover {
  background-color: lightgrey;
}
<div class="container">
  <a href="#">Home</a
><a href="#">Media</a
><a href="#">Store</a
><div class="aboutcontainer">
<a class="button" href="#">About</a>
  <div class="about">
    <a href="#">About2</a>
    <a href="#">About3</a>
  </div>
</div>

</div>

You'll notice in the snippet above, we had to remove overflow:hidden from .container. That is because now that the element is positioned absolutely within its parent element, it gets hidden when it overflows from .container. You had applied overflow:hidden so the end elements wouldn't stick out over the border-radius, so I simply added a border-radius to the first element.