How is the width of an <svg> determined when margins are involved? - html

It seems like the width of an <svg> element is set based on the size of the parent, but ignoring margins:
Why is this? And how can I make an <svg> behave like any other block element when it comes to sizing?
Fiddle: http://jsfiddle.net/4p3ww/

There is no way for some SVG content to say it wants to take up whatever space is available after borders, padding and margins have taken their share (there is no way to create SVG that does NOT have an intrinsic width/height since the 'width' and 'height' attributes default to 100%).
https://wiki.mozilla.org/SVG:Sizing
Seems like there is still a debate on how different browsers should render these, so I'd be careful. Even with height/width attributes and max-width CSS, it still rendered pretty weird for me.
http://jsfiddle.net/4p3ww/3/

Just don't use <svg> and <img> as if they were block elements. They are not (Is <img> element block level or inline level?).
If you wrap your <svg> into a <div> with the contained class as per your example, you get results more in line with what you'd expect: http://jsfiddle.net/gLndw/

Related

Negative margin limit with images

See My Fiddle:
http://jsfiddle.net/5BEsZ/
I've discovered something very strange that I haven't seen documented anywhere else... Was wondering if you all had a solution.
You'll notice the negative margin hits a limit at around -212% for image elements. Is there a reason for this? Can you think of a work around?
Why I Need This (what I've tried):
I'm making a fluid layout and I want to display a rating system. I have a sprite sheet of stars (similar to the one in the fiddle) that I want to reuse at various sizes.
Because the size changes I can't use a background image. So I decided to use an image inside a container with a variable width and overflow:hidden. The sprite sheet adjusts to the width of the container and the container's viewable content is determined by a padding-top:20%. This is so it can be fluid with its width (since every star is a box, the total height is 20% the width).
Then I try and position the star image inside the container with margin-top. I tried using position:relative and a top:-X%, but because the container technically has no height this was causing issue on mobile phones (-100% of 0 is 0, etc).
So I assumed negative margin would work, but then discovered this strange issue!
NOTE: Because it affects only the last row I can make it work in my situation by using a padding-bottom instead of top (thereby bumping every star row up 1), but this isn't an adequate solution for me because it just ignores the problem. What if I wanted quarter stars?
I've updated your fiddle. img tags are "inline" elements by default, which impacts the way margin is calculated relative to the containing element. By forcing the image element to be rendered like a block (display: block), you're able to achieve the results you were expecting. A div element is a block by default.
As a side note, you'll want to avoid using inline styles (a different sort of "inline"!) wherever possible. Typically your styles would be included in a stylesheet instead of in a style attribute directly on the element. I included the fix (display: block) in the attribute to match the code style of your html.
I don't know why, but if you float the image the problem goes away.
<img src="http://www.whitepages.com/common/images/sprite_stars.gif?1343868502" id="stars" style="width:100%; float: left;" />
So, the answer to fix your problem: http://jsfiddle.net/5BEsZ/2/
If anyone could explain why this happens?

Should I always explicitly set width on floated items?

Here and there I see suggestions that I should always set width on floated items. But when I'm exploring CSS of popular web-services (such as Twitter/Google), I see that almost nobody does that.
Is it still considered good style to always set width on floated items? In which cases should I set 'width' property and when it can be safely omitted?
Some quotes:
SmashingMagazine says that:
“You should always set a width on floated items (except if applied directly to an image – which has implicit width). If no width is set, the results can be unpredictable.”
HTML and CSS: Design and Build Websites book says:
When you use the float property, you should also use the width property to indicate how wide the floated element should be. If you do not, results can be inconsistent but the box is likely to take up the full width of the containing element (just like it would in normal flow).
Well it really depends on the browser, you must check the results in multiple browsers to be sure that none of them "misunderstood" your settings. I'd set a width anyway, because no browser can misunderstood that.
Block element takes the full width of the parent. If you use float it will not take the full width, the width would be how much the element width it is.
i use width with floating elements in percentage of the containing div , the only problem you get is that the containing div might not wrap arround its content , so you have to put on the main div overflow:auto

How can I scale a container to match its scaled (or otherwise transformed) content?

I have a <div>, inside of which some complicated content is rendered with a scale transform applied. My problem is that the <div> takes up the same space that it would have taken even if no transform was applied. I've made a jsFiddle snippet to illustrate what I mean.
I think I can understand why the behavior is like this, but is there any way to make it so that the container takes as much space as its content with scaling (and other transforms, if possible) applied?
I should note that explicitly setting the width and height of the <div> outside affects the contents of the scaled text (and this is not desired behavior in my case). Putting the scaled content in an <iframe> is something I'd like to avoid.
Without resorting to Javascript, there isn't any way to do this, I don't think. CSS transforms don't affect layout flow for elements near the transformed elements, they only change the coordinate system within that element; so children are affected, but not parents or siblings (MDN has some more detail on this).
There's a great answer here that might be a JS-based partial solution for you: https://stackoverflow.com/a/10913299/2524360
I don't know if this answers your question, but it doesn't seem to accept 0 as a value. The browsers scales from 1, as in 100% to e.g. 4, or 400%.
transform:scale(1,4);

Why does display:block not stretch buttons or input elements

I'm trying to understand the reason behind this problem:
What's the underlying reason behind <button> or <input> elements not behaving like other elements when set to display:block!
I'm not looking for workarounds to fix this problem, so please don't point me to this answer because it doesn't answer the question.
Here's a js-fiddle that illustrates the problem
Update 1: #Pete is correct, the default size attribute of an element is what sets the size even on block, as you can in this fiddle the size and cols attribute of <input> and <textarea> changes their width. That solves part of my question.
With that in mind, my question is now, why is the <button> element not behaving like other block elements? It's a mystery to me!
Button, Input and other form elements are actually replaced elements - see this answer: HTML5: Non-replaced vs. replaced element?
Additionally, button and input are inline elements. Thus, reading the MDN docs regarding visual formatting here: https://developer.mozilla.org/en-US/docs/Web/CSS/Visual_formatting_model, as well as the w3c docs here: https://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width, you can conclude that for replaced inline elements:
If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
Therefore, button and input have an intrinsic width set to their content (or the size attribute on input, if used). That's why just specifying display: block doesn't do anything to the size of a button or input. You also have to override the intrinsic width of the elements.
Update: While researching more after answering this question, I found a much older answer which goes into much more detail about this same issue. You can find it here: https://stackoverflow.com/a/27605483/630170.
I think that a default value is assigned to the size attribute of inputs which means unless you specifically override it, your width won't be 100%
If you look at the firefox specification and scroll down to the section about size, you can see that they have a default value of 20
I'm not sure about the properties for the button that cause that not to be 100% width when changed to block
Some elements like <input>, <textarea> or <button> have default styles included, like their border or, in your example, their size. I think the reason is, that HTML has still to be usable with the simplest markup and does not require any styling from css (or inlined attributes) to work.
The fact that display: block does not change this behaviour is, that an input field already is a block element. But in contrast to most other elements it does have a default value on the width attribute which is not 0.
The reason I think is pretty simple: If you create an <input> field and use no css or styling, you simply wouldn't see it, like you do not see an unstyled <div>.

Why does making a div display:inline make it suddenly go smaller?

Pretty simple question really when I make a div inline it seems to lose its height?
Any ideas? I'm scratching my head....
UPDATE: after fiddling around I found another display type called "inline-block" which seems to allow me to keep items inline (unordered lists for example) and then set a height for them.
Is this a solution to the problem of inline elements losing the height setting?
Inline elements don't have heights... You've reached the very essence of difference between inline and block.
The height of an inline element is dictated by the line-height of the parent element, with whose contents they're now in-line. Therefore they're unable to have an explicit height of their own.
Similarly for the width, except that's dictated by the width of the contents.
I have found that if I use an inline-block I can make elements sit inline but not lose the height.