Calc of max, o max of calc en CSS

122

¿Es posible hacer algo como esto?

max-width: calc(max(500px, 100% - 80px))

o

max-width: max(500px, calc(100% - 80px)))

en CSS?

Arnaud
fuente
¿Los ha probado usted mismo?
Kyle G.
5
Como dijo @ gert-sønderby, solo use estos dos: min-width: 500px; ancho: calc (100% - 80px);
paulie4

Respuestas:

11

min(),, ¡ max()y clamp()finalmente están disponibles!

A partir de Firefox 75, Chrome 79 y Safari 11.1 (excepto clamp).

min()y max()tomar cualquier número de argumentos.

clamp()tiene sintaxis clamp(MIN, VAL, MAX)y es equivalente a max(MIN, min(VAL, MAX)).

min()y max()puede estar anidado. Se pueden usar tanto dentro calc()como fuera de él, también pueden contener expresiones matemáticas, lo que significa que puede evitarlas calc()al usarlas.

Por lo tanto, el ejemplo original se puede escribir como:

max-width: max(500px, 100% - 80px);
usuario
fuente
1
Por lo que vale, MS Edge para macOS (Versión 81.0.416.68) también los permite. Uno asumiría que la versión de Windows también funciona. No conozco la versión mínima compatible.
jhelzer
1
El nuevo Edge es esencialmente Chrome, sus versiones siguen a la de Chrome. Los datos completos de compatibilidad del navegador se encuentran al final de las páginas vinculadas.
usuario
115

Una solución CSS 'pura' en realidad es posible ahora usando consultas de medios:

.yourselector {
  max-width: calc(100% - 80px);
}

@media screen and (max-width: 500px) {
  .yourselector {
    max-width: 500px;
  }
}
Andy
fuente
3
¡Gran solución! Lo he usado en realidad para la altura mínima, aparentemente también puede usar consultas de medios para max-height+1
avishic
102

No, no puedes. max()y min()se han eliminado de Valores y unidades de CSS3. Sin embargo, pueden reintroducirse en valores y unidades CSS4 . Actualmente no hay ninguna especificación para ellos, y la calc()especificación no menciona que sean válidos dentro de una calc()función.

David Storey
fuente
1
Puede utilizar JavaScript para obtener el estilo calculado (en realidad, el estilo utilizado) del elemento. Elimine 80px y compárelo con 500 para ver cuál es mayor. Algo como var val = parseInt (window.getComputedStyle (el, null) .getPropertyValue ("width")) - 80) para obtener el ancho - 80 y el.style.maxWidth para establecer el ancho máximo.
David Storey
10
Gracias. Sin embargo, preferiría una solución CSS pura.
Arnaud
41
Siempre que haya una pregunta de CSS y una respuesta comience con "Puede usar JavaScript", es incorrecta. Hay muchas razones válidas para querer mantener todo el código de presentación en CSS. Todos, no la mayoría.
b264
8
Parece que min () y max () están de vuelta en el módulo de valores y unidades CSS, nivel 4 (borrador del editor, 1 de septiembre de 2017) Enlace: drafts.csswg.org/css-values/#calc-notation
Jakob E
5
PERO hay una solución al problema, sigue desplazándote a @andy responde a continuación
Offirmo
44

Una solución alternativa sería usarlo widthsolo.

max-width: 500px;
width: calc(100% - 80px);
David Mangold
fuente
3
Esta es una buena idea, pero si entiendo correctamente la pregunta de @ Arnaud, él quiere el ancho máximo de 500pxo 100% - 80px. Su solución limita el ancho máximo 500pxincluso si 100% - 80pxes más grande.
Theophilus
2
Pero es lo mismo que usar, min()por lo tanto, puede ser útil para otros.
Seika85
17
Sin embargo, me parece que usar min-width en lugar de max-width en el ejemplo anterior podría ser equivalente al comportamiento solicitado.
Gert Sønderby
1
La respuesta me ayudó a agregar un margen a un contenedor flexible una vez que el ancho de la página se redujo. codepen.io/OBS/pen/wGrRJV
ofer.sheffer
Publiqué una solución que demuestra que el comentario de @ GertSønderby es de hecho la solución correcta.
SherylHohman
13

Si bien la respuesta de @david-mangold anterior , fue "cercana", fue incorrecta.
(Usted puede usar su solución si quieres un mínimo de ancho, en lugar de un máximo ancho).

Esta solución demuestra que el comentario @ Gert-Sønderby a esa respuesta hace el trabajo:
La respuesta debería haber utilizado min-width, no max-width.

Esto es lo que debería haber dicho:

min-width: 500px;
width: calc(100% - 80px);

Sí, use min-width más width para emular una función max () .

Aquí está el codepen (es más fácil ver la demostración en CodePen y puede editarlo para su propia prueba).

.parent600, .parent500, .parent400 {
    height: 80px;
    border: 1px solid lightgrey;
}
.parent600 {
    width: 600px;
}
.parent500 {
    width: 500px;
}
.parent400 {
    width: 400px;
}

.parent600 .child, .parent500 .child, .parent400 .child {
    min-width: 500px;
    width: calc(100% - 80px);
    border: 1px solid blue;
    height:60px;
}

.ruler600 {
    width: 600px;
    border: 1px solid green;
    background-color: lightgreen;
    height: 20px;
    margin-bottom: 40px;
}
.width500 {
    height: 20px;
    width: 500px;
    background-color: lightyellow;
    float: left;
}
.width80 {
    height: 20px;
    width: 80px;
    background-color: green;
    float: right;
}

.parent600 .wrong, .parent500 .wrong, .parent400 .wrong {
    max-width: 500px;
    width: calc(100% - 80px);
    border: 1px solid red;
    height:60px;
}
<h2>(Min) min-width correctly gives us the Larger dimension: </h2>
<div class="parent600">
    600px parent
    <div class="child">child is max(500px, 600px - 80px) = max(500px, 520px) = 520px</div>
</div>

<div class="ruler600"><div class="width500">500px</div>20<div class="width80">80px</div></div>

<div class="parent500">
    500px parent
    <div class="child">child is max(500px, 500px - 80px) = max(500px, 420px) = 500px</div>
</div>

<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>

<div class="parent400">
    400px parent (child expands to width of 500px)
    <div class="child">child is max(500px, 400px - 80px) = max(500px, 320px) = 500px</div>
</div>
<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>


<h2>(Max) max-width <em>incorrectly</em> gives us the Smaller dimension: </h2>
<div class="parent400">
    400px parent
    <div class="wrong">child is min(500px, 400px - 80px) = min(500px, 320px) = 320px</div>
</div>
<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>

<div class="parent500">
    500px parent
    <div class="wrong">child is min(500px, 500px - 80px) = min(500px, 420px) = 420px</div>
</div>

<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>

<div class="parent600">
    600px parent
    <div class="wrong">child is min(500px, 600px - 80px) = min(500px, 520px) = 500px</div>
</div>

<div class="ruler600"><div class="width500">500px</div>20<div class="width80">80px</div></div>

Dicho esto, la respuesta de @ andy anterior puede ser más fácil de razonar y puede ser más apropiada en muchos casos de uso.

También tenga en cuenta que, eventualmente, una max()y una min()función pueden introducirse en CSS, pero a partir de abril de 2019 no forma parte de la especificación.

SherylHohman
fuente
1
¿Por qué el voto negativo? Todo lo dicho es correcto y todas las fuentes han sido vinculadas y acreditadas.
SherylHohman
1

@Amaud ¿Existe alguna alternativa para obtener el mismo resultado?

Existe un enfoque CSS puro que no es js que lograría resultados similares. Debería ajustar el relleno / margen del contenedor de elementos principales.

.parent {
    padding: 0 50px 0 0;
    width: calc(50%-50px);
    background-color: #000;
}

.parent .child {
    max-width:100%;
    height:50px;
    background-color: #999;
}
<div class="parent">
  <div class="child"></div>
</div>

Jicub
fuente