How can I specify that the width of a given element should be the "maximum available width", once its horizontal margins, its parent's horizontal padding, etc. are taken into account, and also assuming that the parent's width has not been specified explicitly?
BTW, contrary to what one may think, width:100% is decidedly not the answer to this question (see here, for example).
(There are many questions on SO that seem to ask the same thing as this one, but on closer inspection one finds that those are far more specific than this one, and their answers depend on very specific details of some code presented in the question. Here I'm looking for as general as possible an answer.)
Fairly Easily
What you describe is the default behavior of anything that is display: block. So this fiddle shows a "normal" layout for some mixed inline and block elements contrasted to all those elements simply set to display: block.
To do this you can add display: table; to the parent.
The childrens will always fill 100% of the parent element.
Check this JSFiddle that I put together for you.
Related
I’m writing a template for marking on flex/box. And faced with the problem of emulation of some properties. At the moment, I decide them on JS. What complicates code.
So I decided to try to use the property of table-cell for child elements whose parent has the property display: block. Yes, it’s not right, but it works!
When I’m trying to break the table-cell elements to strings, I ran into a problem. And that’s how I tried to solve them:
If the child blocks table-cell overflow the parent horizontally, then
the following blocks are not transferred to the new line. And it is
logical. Example: Nowrap in link.
If I use the cancel flow, I lose equal to the width of columns for the element to be wrapped to the next line. So, this method only works for IE9+. I’m willing to drop IE7, but not ready to abandon IE8. Example: Wrap nth-of-type in link.
If I use the blocks which separate the table-cell on the line, everything becomes fine! But this complicates the CSS and JS code. Example: Wrap with break elements in link.
Example: http://codepen.io/anon/pen/GmgXmO
What ways to break table-cell can be applied, besides the above described options?
An example of a 12 column layout, fix the problem of calculation of the width percentage: http://codepen.io/anon/pen/PmwRvK
In order to make it clear why I do this.
I will be glad to hear your answers! And excuse me for my bad English.
P.S.: Ignore the strange size of the width in percent. It is calculated
according to the formula:
(100 * element.clientWidth / element.offsetWidth).
The smaller size, so it is more. Funny. This rule is applicable only to
the parent display: block containing the child elements display: table-cell
NOTE: the motivation behind this post is solely to understand CSS better. CSS remains mostly voodoo to me (despite hours and hours and hours of studying it), and I'm certainly not looking for any more voodoo (i.e. more "workarounds" or "hacks"). I'm looking for insight into CSS.
I have found two approaches for centering a div within its container. (Throughout this post I'll call the div to be centered #inner-div.)
The first approach is based on giving #inner-div the spec margin:0px auto;; the second one consists in giving #inner-div the spec display:inline-block.
AFAICT, the margin:0px auto approach also requires explicitly setting the width of the div, as illustrated in this jsFiddle; the key bit of CSS is
#inner-div {
margin:0px auto;
width:100px;
}
(To see what happens if the width specification above is omitted, see this jsFiddle.)
Similarly, AFAICT, the display:inline-block also requires 1) giving the spec text-align:centered to the element containing #inner-div, and 2) preventing the extraneous bottom-margin that the display:inline-block entails for #inner-div (this could be achieved, e.g., by giving the spec vertical-align:top to #inner-div and, AFAICT, any additional descendants with display:inline or display:inline-block). See this jsFiddle, in particular the following bits of CSS:
#outer-div {
text-align:center;
}
#inner-div {
display:inline-block;
vertical-align:top;
}
I find both approaches problematic. The second approach is clearly problematic, since the display:inline-block gives the affected div text-like semantics, resulting in unexpected behavior (like the seemingly gratuitous bottom margin mentioned above).
The first approach, on the other hand, requires the specification of #inner-div's width. This precludes the possibility of having this width specified implicitly by the widths of the contents of #inner-div. I don't like this: I often need to center divs whose width is difficult for me to determine, even at run-time (e.g. this width may depend on font-metrics, or the way the flow works itself out within #inner-div, etc.). After all, as the jsFiddle's given in this post show, the browser already computes the height of the #inner-div based on its contents (IOW, one doesn't have to explicitly specify #inner-div's height for the browser to do the right thing). Why can't the browser also compute #inner-div's width?
It seems to me that any reasonable layout system would allow one to say to the browser: "figure out the width of this div, based on the width of its contents, and center it within its container".
My question has two parts:
I'm looking for a well-informed confirmation that CSS really does not provide any way to direct the browser to compute the width of a div (based on its contents) and then center said div within its containing element; and
if the answer to the last question is "yes", is this so merely due to poor design on the part of the creators of CSS, or is there a good reason for CSS not to support this natural (to me at least) functionality?
Note: these are difficult questions; the second, in particular, requires not only a a command of the CSS standard, but also an understanding of the design of CSS itself: a pretty tall order!
Without a given width to work with, how would the browser know how to calculate the flow wrapping? It would be nice to tell the browser to 'make it look good', but they just aren't that smart. I feel your pain though; a fixed minimum width with a on-overflow-expand would make life easier.
How about setting the width as a percentage of the page width, or setting it dynamically with script?
I agree setting the div to a inline-block/table-cell/whatever introduces more trouble than it is worth.
BTW "margin: auto;" is enough, "margin:0px auto;" seems contradictory.
The div is the quintessential block level element, and the span is the inline counterpart. They are the simplest possible form of that display type, with no other properties. In a great many cases I will give either of them the style:
display: inline-block;
This makes them behave in a very handy way. For div it means boxes that will easily sit next to each-other, while maintaining their width and height as defined. For the span I can use this to make colorful rectangles. The inline-block display is great for so many things, but I have never seen an element that starts as an inline-block without anything else going on.
Images (img) are, but they are obviously not suited for the same things as a div, they have that style, but they fulfill a different purpose.
So is there an element that I don't know of that is the quintessential inline-block, or is this left out?
And if not, why? The uses of inline-block are numerous, so it seems like there should be some element that takes that basic form.
There's no such element, and there are some good reasons why not.
inline-block has several uses in contemporary web design. However it is not part of the original design, which only includes block and inline elements. Instead it derives from <img> as added by NSCA Mosaic. (Which uses the wrong markup and helped defeat the original "responsive design". I think we've only just started to fix the problems with img).
Further down the timeline, inline-block still wasn't part of IE4 or 5, or any version of Netscape. It wasn't part of the early HTML4 era. So we wouldn't expect to find your hypothetical element in that version of the standard. inline-block only appears in CSS2, which came after HTML4. (Look at the reference section in each standard).
Unlike block, inline-block is affected by whitespace in the markup. It's implied by the name, and it's what you'd expect from looking at <img> in the middle of some text (aka wordprocessor object anchored "as character"). But beyond its origins there, the whitespace-dependent markup soon becomes very troublesome. I wouldn't expect W3C HTML5 to enshrine this in a new element.
Specifying it would certainly involve argument about "semantics", separation of content and presentation etc. (As well as what to call it :). And if the default rendering makes whitespace significant - is that not part of the semantics of that element? Consider using images to represent words - or individual letters of a word (with appropriate alt text). This illustrates that the presence of whitespace (or not) around this element would be semantically significant, just like the presenceofwhitespaceseparatingwordsissemanticallysignificant. That seems like a big problem to me.
inline-block is often promoted as a modern alternative to using float everywhere. But neither is genuinely suitable. This is why CSS3 will standardize new layout modes: "flexbox" and "grid", to support modern responsive designs with genuine, clean markup. No dummy markup (or dummy generated content). No hacking around whitespace-dependence.
The only elements I can think of that have an in-line appearance, but allow for a width and height to be set, are:
img,
input,
textarea
select, and
button
The only element here, though, that can take HTML content is the button element; which is not an ideal use of the button since it's intended to be an element with which the user might/should interact; rather than simply a container element.
While you may have multiple uses for such an element, there's no convincing reason, given the ease with which the display property might be changed, that the W3C, or any other authority, should explicitly define one; especially given that the only difference between inline and inline-block is the ability to assign dimensions and margin.
The img tag is inline-block by default:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img
Edit: You can check this SO question: Is <img> element block level or inline level?
I have read (actually here on SO, but cannot find the post at the moment) about a way to hide elements with negative margins.
I recall, that the answer contained a deep explanation on why to do this, and the benefits over other methods (visibility: hidden; position: absolute;, display: none). And yes, the method provided a way to remove the element out of the document flow (possibly hackish, not valid).
Have I been dreaming about this or there is such a way? If there is, then yes, I would love the little in-depth explanation.
Thanks in advance!
Are you trying to hide block level elements like a div, or just the text on a link that's got a background image, for instance. If it's the second item, the CSS you're looking for is text-indent. I've used it in the past like this:
a.button {
/* .button is a for instance class name */
text-indent: -9999px
}
This will leave the block level element (the a tag) and any background you've placed on it, in the document flow, but will move the text off screen. This is a technique I've used in the past, but be careful of the text you're hiding--the search engines look at this as a quasi-black hat technique. Just make sure the hidden text doesn't look like keyword stuffing or obvious spam terms and you'll be fine.
Hope this helps.
Using negative margins is generally considered a more "accessible" way of hiding elements. Absolute positioning OR floating will remove it from the document flow.
This article summarizes several image replacement techniques.
http://www.mezzoblue.com/tests/revised-image-replacement/
HTH!
Either you have been dreaming or you have become a victim of cargo cult coding. The obvious disadvantage of excessive negative margins is that you are relying on a maximum window size. (Excessive negative text-indent also has that problem and others.) Anything larger and the element becomes visible again. Add to that that it is nowhere specified what to do with negative margins of that magnitude.
Only with display: none you can remove an element reliably (as if it was not there). Absolute positioning takes an element out of the normal flow, which is not the same as removing it.
I have a page generated by a database. It creates a DIV for each entry (extremely simplified for sake a question). Each of these DIVs have a set width, and float left.
However, these DIVs don't have a set height, so occasionally the following as depicted in the image happens. Is there a good way to prevent this from happening, and the white space just 'collapsing?'
The link to the prototype site. Here
I think this article would help you:
http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/
Depending on what you have control over, you could always add clear: left; to every other element in your 2-column scenario.
Though, I beleive that the second "The Postal Shoppe" would actually be on the left, and the Brynwood Pak N Ship would be in the right column.
The problem isn't so much that "Brynwood Pak N Ship" isn't collapsing the white-space, it's that the second "The Postal Shoppe" is getting hung up trying to move all the way to the left column by the bottom right corner of the "Express Pack & Mail Center."
Setting clear: left will ensure those entries always move down far enough to "suck up" to the left edge of their parent container. But you will still see some un-evenness using that attribute; the "Brynwood Pak N Ship" will line it's top up with the newly-cleared "Postal Shoppe" showing a tiny gap at the top. Still probably preferable to what's going on currently.
You can add a clear: left attribute to every other div. Alternately, you could try using display: inline-block instead of floating left, but it's not as widely supported (I think it breaks in IE 6 or older), so you'd have to see what hacks are out there to make it work universally.
I suggest giving every box an equal height. This is visually better, and it solves your problem in one go!
I think this is difficult to solve in CSS. I like the suggestions other users have made with 'display:inline-block' and setting the height to be fixed. They both have minor drawbacks, but the situation will be better than it currently is.
If you are going to solve this "properly", we first need to agree what the proper solution is. I think it would be to have two columns, and for each element that has to be added, it is appended to the end of the currently least-full column. This won't necessarily result in elements alternately being placed in column 1 then column 2. Sometimes two (or more) small elements will be placed in column 2 to compensate for a large element in column 1, for example.
I doubt something as complicated as this is possible to define in CSS (but I've been surprised by what can be done before). It could be done using Javascript though. You could have a solution that does a fairly good job if Javascript is disabled using a purely CSS solution, and if Javascript is enabled you could arrange them more elegantly.
I'm not sure it is worth the effort of implementing this though. Some of the existing suggestions seem reasonable compromises, and if it were me, I'd probably go with the inline-block solution, but I thought I'd throw this idea out anyway.
This can be solved now using flex-direction and column-count:
.parent {
column-count: 2;
column-gap: 1.25rem;
}
.child-class {
flex-direction: column;
display: inline-block;
width: 100%;
}
I'm not sure if it's supported in all browsers but it's an easy css solution.