I have a situation where I would like an HTML img which has not yet loaded to have a pre-set height. The reason is that this height will be used in a calculation that may fire before the image is fully loaded and needs to remain accurate. I tried the following:
<div>hello<img src='http://example.com/invalid.gif' class="testimage"> there</div>
and put in some css
.testimage {
height: 200px;
width: 200px;
}
and at least in Firefox 5, the extra space is not rendered (and oddly, the broken image doesn't show either, just a blank space). That is, until I add display: inline-block. In at least some other browsers the default display of inline produces the desired result. Is this expected? If so, why?
Here's a jsFiddle as well: http://jsfiddle.net/uYXD4/
it says here that images are inline elements - http://htmlhelp.com/reference/html40/special/img.html
On the other hand take a look here - Is <img> element block level or inline level?
It looks like the <img> element is kind of both inline and block. No strict rules defining it, so probably the browser vendors make their own decisions about the defaults. So your best bet is to reset their assumptions to display: inline-block
Images are replaced elements:
An element whose content is outside the scope of the CSS formatting model, such as an image, embedded document, or applet. For example, the content of the HTML IMG element is often replaced by the image that its "src" attribute designates.
For replaced elements, display: inline-block is supposed to have the same exact same efffect as display: inline, which is the default.
So this may be a possible explanation for that strange behaviour in some browsers*:
They treat only completely loaded images as replaced elements, and otherwise treat them as non-replaced elements. That makes sense after all, and the standard does not explicitly disallow that. As a consequence, there's 3 possible scenarios:
replaced element, inline or inline-block doesn't matter, height property works
inline non-replaced element, height attribute has no effect
inline-block non-replaced element, height property works
Loaded images always qualify as 1., and broken/loading images may qualify as 1. or 2. (or 3. if you set display: inline-block explicitly)
*Not sure if that's how things actually work though.
Why not use something like
<img src="..." width=400 height=200>
I'm doing the exact same thing and it works quite well. Another option is...
$('.myimg').load( function() { /* ops */ } );
though I don't know if that waits to load the image in ALL browsers or not
Related
I have a div that contains several inline-block children:
The DOM looks like this:
It has the following CSS:
Each child has the following css:
If one unchecks and rechecks the display: block line marked above in the Chrome debugger, the div now looks like this:
Note that there is now space between the labels, and they are more readable. However, the CSS used to render this is presumably identical. Moreover, the div is actually still display: block when the specific selector's display: block is unchecked; it just obtains this from a less specific selector (in my case, the UA stylesheet for div).
I want the div to render the second way - is there a way to make this happen? How is the div supposed to be rendered, and where does the spacing between the display: inline-block elements come from?
UPDATE: This is probably caused by a weird interaction between Chrome's renderer and Meteor's Blaze rendering engine, and won't be seen except on highly dynamic pages.
This is a result of whitespace being evaluated. You can throw:
font-size: 0;
on the parent div and this will go away. Alternatively, adjust your markup to remove space between the list items.
<div> defaults to block
<span> defaults to inline
Is there one that defaults to inline-block?
If not, what special tag name would be appropriate for me to apply 'inline-block' using CSS?
Or should I stick to using a class?
From what I can tell the <img> tag is the only inline-block by default. To be on the safe side I would recommend a class, you never know when changing all elements of a certain type will come back to bite you. Or, you could always make up your own tag and assign display:inline-block; to it. This way you aren't changing the default functionality of standard elements...
EDIT
It also appears that button, textarea, input, and select elements are also inline-block
Sources:
According to this img is inline-block http://dev.w3.org/html5/markup/img.html#img-display
And here claims that button, textarea, etc. are as well: http://www.w3.org/TR/CSS2/sample.html
EDIT #2
While the source above claims that img tags are inline-block it seems (thanks to Alohci) that they are just inline http://jsfiddle.net/AQ2yp/
The following were tested in Firefox:
button is inline-block: http://jsfiddle.net/GLS4P/
textarea is inline: http://jsfiddle.net/235vc/
input is inline: http://jsfiddle.net/RFKe8/
select is inline-block: http://jsfiddle.net/5B4Gs/
Is there one that defaults to inline-block?
Strictly speaking, no there isn't. The W3 HTML specifications do not ever specify default CSS property values for any elements. They do provide a "default style sheet" for HTML 4, but developers are only encouraged to use it - it is not a requirement or any sort of mandate. The HTML 5 specifications indicate "typical default display properties" but, again, those are not required (also keep in mind that HTML 5 is still a working draft anyways).
So that leaves all default values up to the browser and how the developers actually feel elements should be displayed to a user. No one can guarantee that a specific element will display as inline-block or any other way in someone's browser. You should always explicitly set that if you want it to happen. Don't rely on "defaults."
If not, what special tag name would be appropriate for me to apply 'inline-block' using CSS? Or should I stick to using a class?
This is up to you and how you are designing your pages. You should always use elements that are semantically appropriate to the content contained within them. If the element will always be used in a context which will require inline-block display, by all means set it to that in your style sheet. Otherwise, you will have to resort to classes or more specific selectors in order to make your elements display properly.
Here is a Fiddle that gets the default display value for a majority of HTML tags.
Fiddle
In chrome, the default inline-block elements are: "INPUT", "BUTTON", "TEXTAREA", "SELECT"
My solution to this is declaring what I call a slice.
CSS
sl {
display: inline-block;
}
Usage
<sl>inline block stuff</sl>
You can check my codepen with all HTML elements and their display property by default. Some tags are syntax-broken, but it does not matter for our purpose.
Currently, there are 5 elements with display: inline-block in FF :
<button>
<select>
<meter>
<progress>
<marquee>
And additional 2 (including 5 above) in Chrome:
textarea
input
In principle, it depends on the browser what the default value for the display property is for each element. Even HTML5 drafts do not prescribe what values must be used, though it presents “expected rendering” of elements in terms of CSS.
According the default style sheet for HTML in the CSS 2.1 specification, the elements that have display: inline-block by default are button, input, select, and textarea. Browsers use such settings, except that in Firefox, this only applies to button and select.
In the Rendering section of HTML5 CR, the meter and progress elements are additionally describes as having inline block as “expected rendering”, and browsers that have implemented these elements appear to behave that way. The keygen element is also described as being an inline block, but Firefox does not do that (it implemented keygen internally as select in the DOM); IE does not support keygen at all; Chrome implements it as suggested.
Since all of these elements have rather specialized meanings, functionality, and rendering idiosyncracies, none of them is adequate for general use as an element that is an inline block by default and may have various meanings. What you can use for such an element is normally span or div, depending on whether you prefer inline or block as the default rendering.
Now you can create a Custom Element (for example: <inline-block> or whatever) that will have its CSS property display set to inline-block by default.
customElements.define( 'inline-block', class extends HTMLElement {
constructor() {
super()
this.attachShadow( { mode: 'open' } )
.innerHTML = `<style> :host { display: inline-block } </style>
<slot></slot>`
}
} )
#hw { background-color: lightblue }
<inline-block id="hw">Hello World</inline-block>
button, textarea, input, and select default to inline-block.
In the event you would want to inline-block a div you'd give it a class name.
.inline-block {
display: inline-block
}
Then...
<div class="inline-block"></div>
CORRECTION
I was mistaken about img. It seems it defaults to inline and not inline-block
This isn't really a true answer to the question right now, but with enough support, it may someday be.
<seg> short for "segment". As in, segments of a line.
with the polyfill:
<style> seg { display: inline-block; } </style>
It really would be nice if there was an official one, but there is not, so here is the best (IMO) suggested name for such an element that I know of.
YES there is an element that defaults to inline.
The answer is the span element.
<span>
Why is the default display style for image inline instead of inline-block?
Is there any difference between inline and inline-block for img elements, from what I can see it behaves exactly in the same way.
IMG is an Inline & Replaced element.
A replaced element is any element whose appearance and dimensions are
defined by an external resource.
As per W3C
The IMG element has no content; it is usually replaced inline by the
image designated by the src attribute, the exception being for left or
right-aligned images that are "floated" out of line.
Check this link for more http://reference.sitepoint.com/css/replacedelements
The default browser stylesheets were initially created using CSS1 for HTML3.2, so inline-block was not available or necessary. There's no difference between them for image elements.
References
CSS 1 Specification
HTML 3.2 Specification
The first part of your question is already answered, so I shall not repeat.
For the second part, some browsers like Firefox renders a no-image img tag as a span even when width and height attributes are specified in CSS.
You can try it out yourself with this HTML code:
<img alt='no image' src='about:blank'><br>
<img alt='no image' src='about:blank'id=iblock>
And corresponding CSS:
img {
height: 100px;
width: 100px;
background: cyan;
}
#iblock {
display: inline-block;
}
Or see the difference in rendering effect with this Demo on JsFiddle.
Inline-block allows you to manipulate the object's appearance with box-model styling (such as giving it dimensions), but allows you to keep the object aligned inline, like text.
Inline block is the same as inline, except for it allows you to adjust block properties such as padding and margin. By default, images are supposed to semantically flow with text like a diagram in a news article, that is why all the original attributes are to do with aligning the image with the text flow.
Inline-block is a newer CSS2 declaration, and not fully implemented in IE 6/7.
It's simply an inline element that supports dimension attributes: Embedded content - the img element.
Background: I need to have an inline element to which I can apply width and height via CSS.
AFAIK, img is the only way to have this behavior, currently.
I would rather not have the image point to a transparent pixel GIF on the server. It may be cached, but browsers queue it nevertheless, slowing down overall page speed. Other clients might not be caching at all.
PS No, floating div is not sufficient, it behaves differently from inline elements.
EDIT Sorry, I should have inserted the term "cross browser" somewhere. It must at least be working for FF≥2, IE≥7 and current Safari.
You could use the "data:" URI scheme to embed an image.
Other replaced elements might also work. Setting display to "inline-block" might also be worth looking into.
Can you set:
display:inline-block;
width:50px;
height:10px;
IIRC, images are an "inline block" element, thus they can be rendered inline in text strings, but still have block-like properties.
I guess it will be valid in the W3C validator sense, because the validator does not check whether the link is a resource or not.
However, valid in the broader sense, I would say it is not. An src attribute is required in the IMG tag, and I would say must point to a valid image resource.
I find outis`s "data: URI" idea the best way.
If that doesn't work, a transparent image is your best bet. It's one call, it's a few bytes at best, and will be cached by most clients.
Using "about:blank" as src will cause IE to display red X-boxes. This line of CSS prevents this (in IE 8+), but it's still all a bit hacky:
img[src="about:blank"] {visibility:hidden}
You can accomplish the same thing with a tag.
<p style="height: 400px; width: 400px; background-color: #ffcccc;"> </p>
Height and width are settable. This should be across the common browsers, however I have not been able to test Safari or Chrome using it.
Use a <span> tag with a in it - totally valid - then set it's width and height in CSS, also apply display: block;
Using an empty <span> tag means it will be ignored by screen readers and it won't show up as a broken image when styles are disabled.
It'll also not use up any more bandwidth.
:-D
As I understand, width/padding/margin properties only work on block level elements. However, on INPUT and SELECT elements I am able to specify the width, which works. Should it?
I could write something like this:
<input type="text" style="display:block;" />
But is it necessary?
Can anyone explain please why it works?
Actually, they're not really inline elements, but rather inline-block elements. This allows you to specify width, height and other block-specific properties without the need to break the flow of inline elements. In good browsers you can use "display:inline-block" on any element to achieve the same thing.
The spec says:
Applies to: all elements but non-replaced inline elements, table rows, and row groups
Form controls, such as input and select elements are replaced inline elements (the element is replaced with a form control - the text content of it is not displayed like a normal element).
Since they are replaced, they are not non-replaced, so the width property applies.
Form elements are the black sheep of the HTML/CSS world - there's lots of properties which don't work like normal HTML elements.
While it doesn't answer yor question, you might find the following discussion interesting: http://meyerweb.com/eric/thoughts/2007/05/15/formal-weirdness/
Technically, that's a rendering property which is browser-specific. At this point most browsers do allow you to set the width, but it's not guaranteed (especially on older browsers) and you definitely can run into bugs with it.
The W3 spec for the input element technically makes it an inline element. Inline-block isn't even a part of the W3 spec, it's part of CSS2 (hence older browsers being inconsistent).
IE has some funny bugs if you specify width as a percentage and put a whole lot of text into it, for example.
Long story short, it's almost always safe, just not part of any official spec that I've seen.
Did you thing what happened if that would be not possible? When INPUT element was introduced there was no CSS. And width of INPUT element is absolutely required in HTML for creating proper forms.