57

I'm trying to create a responsive layout in which two boxes sit next to each other if the screen size allows it, and have them below each other if it doesn't. If the boxes are below each other, I'd like them to be centred to their parent. I've set up a jsfiddle to demonstrate the problem:

http://jsfiddle.net/leongersen/KsU23/

width: 50%;
min-width: 350px;
max-width: 100%;

Try resizing the 'result' pane to below 350px. The elements will overlap their parent.

My question:

Why isn't the specified max-width honoured, even though it comes after the min-width?

Lg102
  • 4,733
  • 3
  • 38
  • 61
  • I don't see the problem. They get to 50%, if I make it wider, they keep at 50%, if I make it smaller than 700px, then they keep a min-width of 350px and get wrapped (the second one goes to a new row). What are you expecting to happen? – Francisco Zarabozo Apr 17 '13 at 15:19
  • The red boxes are overlapping the parent element if that becomes smaller than 350px. – Lg102 Apr 17 '13 at 15:21
  • @FranciscoZarabozo - Lg102 seems to expect the max width of 100% to take over when the parent's size is less than the sum of the min width of the child elements. a sort of advisory min width where possible – CodeMonkey Apr 17 '13 at 15:25
  • Do you want this to happen? http://jsfiddle.net/KsU23/3/ – Francisco Zarabozo Apr 17 '13 at 15:26
  • 7
    You did not specifically seek a solution for your desired output in this question, but I believe what you want is `max-width: 350px; min-width: 50%` without any `width` set. [See this fiddle](http://jsfiddle.net/KsU23/4/). – ScottS Apr 17 '13 at 15:29
  • I was under the impression the OP was after better understanding of the way CSS is applied, rather than a fix for the current situation? – CodeMonkey Apr 17 '13 at 15:31

3 Answers3

81

Because of the CSS standards:

The following algorithm describes how the two properties influence the used value of the 'width' property:

  1. The tentative used width is calculated (without 'min-width' and 'max-width') following the rules under "Calculating widths and margins" above.
  2. If the tentative used width is greater than 'max-width', the rules above are applied again, but this time using the computed value of 'max-width' as the computed value for 'width'.
  3. If the resulting width is smaller than 'min-width', the rules above are applied again, but this time using the value of 'min-width' as the computed value for 'width'.

As such min-width always 'wins'. Within a specific CSS rule there's no precedence anyway, all values are applied atomically. Precedence only occurs when different rules all apply to the same element, and even then it is based on specificity first before file order is considered.

Niels Keurentjes
  • 41,402
  • 9
  • 98
  • 136
  • 2
    Precedence only occurs when the *same rule* applies to an element multiple times. i.e. `.foo { bar: fizz; bar: buzz; }` the latter definition takes precedence. In the example, `min-width` and `max-width` are different rules, so precedence doesn't come into it. – zzzzBov Apr 17 '13 at 15:20
  • 2
    That is not really precedence. When a *declaration* is duplicated within a *rule*, it is simply an overwrite of the same value resulting from sequential parsing. The resulting rules (with a rule being a selector and a set of declarations) can have precedence based on the specificity of the selector, or if 2 rules are equally specific the 'cascading' effect of CSS comes into play and the latter definition is considered more specific. – Niels Keurentjes Apr 17 '13 at 15:54
  • 1
    My point was that your post says "Precedence only occurs when different rules all apply to the same element", when it should be "Precedence only occurs when the same style rule is applied to the same element" – zzzzBov Apr 17 '13 at 16:14
  • I highlighted the words *declaration* and *rule* specifically. The first is a single combination of property and value, the second a set of declarations with a selector. You can perfectly well have multiple rules apply to the same selector, for example based on media queries or in cascaded files. As such my statement is valid. You intend to say that **within** a rule the declarations are parsed in the order of notation, and as such a later declaration will override the previous value declared in the same rule. Whilst correct, that's not what I was saying or referring to. – Niels Keurentjes Apr 17 '13 at 16:21
  • @NielsKeurentjes - do you know how this relates to flexbox; flex-basis, flex-grow, etc? – carl-johan.blomqvist Sep 06 '19 at 11:27
  • After looking it up, it seems it's part of your step 1. – carl-johan.blomqvist Sep 06 '19 at 11:32
  • Yes it is. These properties only resolve conflicts after all other rules have been applied. – Niels Keurentjes Sep 06 '19 at 12:27
4

I know, I'm late ... But one exact solution could be this:

p {
    display: inline-block;
    font-size: 15px;
    text-align: left;
    width: 50%;
    border: 1px solid blue;
    min-width: 350px;
}
@media (max-width: 700px) {
  p {
    width:100%;
    display:block;
  }
}
Roland Gautier
  • 345
  • 3
  • 6
  • The new @content query would also work when the percentages are not related to the whole screen. Though it is still a Working Draft, it is already widely implemented, – Fox Sleigh May 14 '23 at 15:20
2

Late aswell but I think the best solution would be the use of min()

width: 50%;
min-width: 350px;
max-width: 100%;

would become

width: 50%;
min-width: min(350px, 100%);

This way you are not depending on media querys which might even not work for your usecase because the width is based on the parent element