Conditionally style an element based on whether its contents overflow it? - css

Say I have a <ul> with height: 100px and overflow: auto, and you are dynamically adding/removing <li> elements to it – so sometimes it is scrollable, sometimes not.
I want to visually indicate when the element is scrollable, so the user can always tell at a glance if there's extra content that requires scrolling to see, even on devices that don't display scrollbars.
In other words, I want some kind of magic pseudo-selector like ul::contents-overflow, which only applies when the contents of the <ul> overflow its content box.
Does anything like that exist in CSS, or do I have to use JavaScript for this?

Related

Cannot get div to widen to include all floated elements

I've converted a bootstrap date module to use only Angular(still in the middle of the conversion). Here is the demo page with the behavior I want to fix.
Click on the input field under "Your Date Range Picker" to see the daterangepicker. I've attached a screenshot of what you should see:
The issue I'm having is that the wrapper(div.daterangepickerdropdown-menu.opensright.ltr.show-calendar) is set to width:auto, but the three child elements, ranges, left calendar, and right calendar are set to float:left. For some reason they end up wrapping so that they stack vertically, and I can't figure out why they aren't side by side horizontally. I've tried playing with clears, setting overflow:hidden to the wrapper, and nothing seems to work. I've spent 4+ hours with the chrome debugger playing with css rules and can't get the wrapper to widen as much as necessary to put all three child elements horizontally.
For a comparison of what it should look like this.
You have nested your dropdown menu within a div with class col-md-4, which has a defined width.
The working demo has placed the dropdown menu outside of this column.
Even though you are positioning it absolutely it is still inheriting the max-width of the column. (you can see this by setting the dropdown menu width to 50%)
You can solve this by changing your HTML structure and positioning your dropdown menu in a similar way to the demo, or by overriding the width using a fixed setting which will adequately fit the child elements, e.g. width: 170%.
The problem here is the following container:
<div class="col-md-4 col-md-offset-2 demo"></div>
You should remove position-relative from the above element so that your date-picker does not inherit properties from it.
Alternatively, you can apply position: relative to the <div class="row"></div> element just above the .demo element and align your date-picker accordingly.

What does setting "open" on the <details> tag actually do, in CSS terms?

I'm upgrading my site to use the <details> tag, for accessibility purposes.
My question is this. When the "open" attribute is set on the <details> tag, as below:
<details open>
<summary>more info</summary>
<ul>
<li>blah</li>
</ul>
</details>
is there anything different in CSS terms about the <ul> tag? It seems to have display: block set whether it's visible or not.
I'm trying to write front-end tests to check that the <ul> becomes visible when the element is clicked, and I'm not sure how to do this without something actually being different in CSS.
JSFiddle here: http://jsfiddle.net/6x2Kc/
In terms of how to detect visibility, Mathijs Flietstra's answer seems to fit the bill.
On the broader matter of what the CSS is actually doing, the HTML5 spec has something to say here:http://www.w3.org/html/wg/drafts/html/master/rendering.html#the-details-element-0
It says:
... the [details] element is expected to render as a 'block' box with its 'padding-left' property set to '40px' for left-to-right elements (LTR-specific) and with its 'padding-right' property set to '40px' for right-to-left elements. The element's shadow tree is expected to take the element's first child summary element, if any, and place it in a first 'block' box container, and then take the element's remaining descendants, if any, and place them in a second 'block' box container.
The first container is expected to contain at least one line box, and that line box is expected to contain a disclosure widget (typically a triangle), horizontally positioned within the left padding of the details element. That widget is expected to allow the user to request that the details be shown or hidden.
The second container is expected to have its 'overflow' property set to 'hidden'. When the details element does not have an open attribute, this second container is expected to be removed from the rendering.
In other words, the content of the details element other the summary element is put into an anonymous block box. (This is a bit similar to how if you make an element display:table-cell then it will be wrapped in anonymous boxes for table-row, table-row-group and table.) It is this anonymous box (and thereby its contents) that is hidden or shown, which is why you can't see the CSS specified values change for any element that you select, only the computed values.
A word of warning though. We don't have many implementations of the details element yet, and the spec text above doesn't require browsers to do it like that, it only says "expected to", so the other browsers may choose to achieve the effect by other means. We can only wait to find out.
In Chrome, the computed values of the ul's height and width properties change to auto when details is closed. Here's a jsFiddle which alerts the ul's height when you click on details.
Setting the open attribute of a <details> element determines whether the height of the content will be the natural height, or zero. If open is present, the height will be the content's normal height, if the attribute is absent, or the content is toggled closed, the height is zero. Here's a quick jsFiddle example.

CSS overflow property

I've found some CSS templates where some classes have the overflow:hidden property, but no size defined. If I recall correctly, block elements stretch to fit their content unless otherwise specified. Since this is not the case, I feel that putting the overflow:hidden is pointless and I can delete it without hesitation. Is this right or am I missing something?
While that's the main purpose of the overflow property, it's not the only effect it has on rendering. The other major effect it has is that setting overflow to anything other than visible (the default) causes a block box to establish its own block formatting context.
This is mainly used to contain floats without the need for a clearfix; however that isn't the only effect of having a new BFC; there are a number of other corner cases that are better described elsewhere in the spec. Also see this lengthy write-up on the reasoning for this behavior (which, oddly enough, has very little to do with containing floats; that actually ends up being nothing more than a side effect).
So if you remove that overflow declaration, you may break float layouts, among other things. I suggest avoiding doing so unless it's absolutely necessary or you're sure it won't affect the layout.
If there are floating children inside that div, then overflow: hidden is probably there to contain them.
overflow: hidden creates a new block formatting context, and elements that create new block formatting contexts contain floats.
It may depend. if your div contains some floated elements you could use
div {
height: auto;
overflow : hidden;
}
as a workaround for the clearing. So I wouldn't delete that rule without seeing the effect on the layout
overflow:hidden can come in handy if you have a child element with a width specified which is greater than the container's max allowed width. Otherwise it will stretch the container.
See example
A common use of this is when displaying a carousel, with floated child elements. The elements need to appear inline, but hidden, so that they can come into vision when the left CSS property is changed.

Making some HTML elements behave as 'block' ones when mixed with inline elements inside an inline parent

I'm trying to get an div with its display property set to inline (or inline-block if I want a margin) to behave correctly in IE (it does in most others).
My situation is this - imagine a workspace in which an item container contains inline items laid out in a horizontal fashion. These items can hold things like text, or images, but also be composite types, say for example a 'fraction', whose numerator and denominator are themselves item containers, containing more horizontal items.
So for example, I might have the HTML:
<div class='item-container'>
<div id='statictext' class='item'>x = </div>
<div id='fraction' class='item'>
<div id='numerator' class='item-container'>...</div>
<hr/>
<div id='denominator' class='item-container'>...</div>
</div>
</div>
Clearly, I don't want fixed width or height for an item or item-container, because they can contain nested content which will increase the amount of space needed (e.g. imagine an fraction inside another fraction), and similarly if I want the width of a static text 'item' to be just big enough to contain the text on one line, i.e. inline.
The problem I think is that it's hard to avoid putting block elements inside my inline 'item'/'item-container' elements, for example the <hr> in the fraction, or if I want say a menu bar at the top of an 'item' that uses the whole width after the width of the rest of the item's contents has been calculated.
I know it's invalid syntax to put an actual block item inside an inline one, although setting the block element's display attribute to inline or inline-block makes things behave correctly in Firefox/Chrome at least. But alas, not in IE.
Is there an adequate fix?
EDIT: I actually used inline-block (with the appropriate IE hack) for 'item' and 'item-container' to get it to work spiffingly in Firefox et al, but IE still treats them as inline, which then subsequently gets converted into block because one of its children is a block.
Don’t use <hr>. You can draw a line using text-decoration: underline or using a bottom border or using an image (say, a one-pixel image stretched to the desired width). Then you can work with inline elements.

CSS Properties: Display vs. Visibility

What is difference between Display vs. Visibility properties?
The visibility property only tells the browser whether to show an element or not. It's either visible (visible - you can see it), or invisible (hidden - you can't see it).
The display property tells the browser how to draw and show an element, if at all - whether it should be displayed as an inline element (i.e. it flows with text and other inline elements) or a block-level element (i.e. it has height and width properties that you can set, it's floatable, etc), or an inline-block (i.e. it acts like a block box but is laid inline instead) and some others (list-item, table, table-row, table-cell, flex, etc).
When you set an element to display: block but also set visibility: hidden, the browser still treats it as a block element, except you just don't see it. Kind of like how you stack a red box on top of an invisible box: the red box looks like it's floating in mid-air when in reality it's sitting on top of a physical box that you can't see.
In other words, this means elements with display that isn't none will still affect the flow of elements in a page, regardless of whether they are visible or not. Boxes surrounding an element with display: none will behave as if that element was never there (although it remains in the DOM).
visibility: hidden;
the element won't be painted AND don't recieve click/touch events, but the space it takes is still occupied
because it's still there for layout purposes, you can measure it without it being visible
changing content will still cost time reflow/layouting the page
visibility is inherited, so this means you can make subchildren visible by giving them visibility: visible;
display: none;
will make the element not participate in the flow/layout
can (depending on the used browser) kill Flash movies and iframes (which will restart/reload upon showing again), although you can prevent this from happening with iframes
the element won't take up any space. for layout purposes it's like it does not exist
will make some browsers/devices (like the iPad) directly take back memory used by that element, causing small hickups if you switch between none and an other value during animations
extra notes:
images in hidden content: in all popular browsers images are still loaded, even though they are within any element with visibility: hidden; or display: none;
fonts in hidden content: webkit browsers (Chrome/Safari) may delay loading custom fonts which is only used in hidden elements, including through visibility or display. This may cause you to measure elements which are still using a fallback font until the custom font is loaded.
display: none removes the element out of the flow of the html whereas visibility:hidden does not.
display:none; will remove the DOM elements visual style / physical space from the DOM, whereas visibility:hidden; will not remove the element, but simply hide it. So a div occupying 300px of vertical space in your DOM will STILL occupy 300px of vertical width when set to visibility:hidden; but when set to display:none; it's visual styles and the space it occupies are hidden and the space is then "freed" up for lack of a better word.
[EDIT] - It was a while back that I wrote the above, and whether I was not knowledgeable enough or having a bad day, I don't know, but the reality is, the element is NEVER removed from the DOM hierarchy. All block level display 'styles' are completely 'hidden' when using display:none, whereas with visibility:hidden; the element itself is hidden but it still occupies a visual space in the DOM. I hope this clears things up

Resources