Apuntes para una regla @IF en Css 3.1.14
Apuntes, sugerencias y divagaciones para la posible existencia de la regla condicional @if en Css
Apuntes para una regla @IF en Css
La finalidad es contar en Css con una vía para modificar las propiedades de un elemento en función del valor computado en una propiedad de un tercer elemento.
Así, por ejemplo, el valor de la tipografía de un elemento dado podrá modificarse al cambiar el valor de la visibilidad de otro, sin que el primero sea descendiente o hermano posterior.
Todo lo que sigue no deja de ser una ocurrencia de un "enredique de Css". Meras conjeturas sin evaluar sus riesgos, problemática, colisión con otras especificaciones css o simplemente su posibilidades reales de ser tenida en cuenta por quien corresponda.
Pese a que lo que sigue sólo es un ejercicio mental, agradeceré tus opiniones. Desde cuestionar el todo por no ser necesaria o no encontrarle uso, pasando por poner de manifiesto los errores o incongruencias que haya cometido o sugerir ideas.
Estructura y Sintaxis de la regla @if
En un principio creo que en Css la regla @if no necesitaría complementos del tipo "else" como en otros lenguajes, ya que en caso de no cumplirse la condición indicada en ella aplicarían los estilos que correspondan por estar ya declarados en las hojas de estilos.
La sitaxis de la regla @if sería como sigue:
@IF (<selector> (<property> <Comparative operators> <value>)) {
/* set de rules */
}
Significado de cada parámetro de la regla @if
- La regla @if
- Se conforma con el identificador del tipo de "at rule" /@if/ seguido de su expresión y a continuación entre corchetes el bloque de reglas.
- La expresión
- Conformada por un único argumento o varios como ocurre con otras reglas arroba como las medias queries. Cada uno de estos argumentos de la regla @if estaría formado por dos partes: el selector del elemento y la condición lógica a cumplir. Esta condición es el par propiedad y su valor unidos por un operador lógico de comparación.
- <selector>
- Indica el elemento del html base de la regla @if. Puede ser cualquiera de los recogidos en las especificaciones, tanto simples (.clase) como selectores complejos, incluidos los formados con pseudoclases y pseudoelementos.
- condición lógica contenida entre paréntesis. Ver Nota 1.
- Esta condición lógica estaría formada por una propiedad css, seguida de un operador lógico de comparación y un valor de los admitidos por dicha propiedad.
Aspectos de la condición lógica:
<property>- cualquiera de las propiedades recogidas en las definiciones de Css.
- <Comparative operators> Operadores lógicos de comparación
- == igual a
- != no igual a
- > mayor que
- < menor que
- >= mayor o igual que
- <= menor o igual que
- <value>
- El valor de la propiedad indicada en el argumento lógico una vez computado. Esto es, el valor a tener en cuenta para evaluar si se cumple la condición lógica debería ser no el declarado en algún momento en los estilos sino el resultante de aplicar al declarado en los estilos (si estuviera) la herencia y/o cascada.
- El bloque de reglas
- Como en cualquier otra at rule o regla de reglas se incluyen entre corchete de apertura y cierre las reglas que se han de aplicar en caso de cumplirse el argumento de la regla @if
Nota 1: Por descarte. No sería aconsejable usar el corchete [ ] pues es empleado en los selectores de atributo. El anidado de paréntesis no sería una novedad, pues ya ocurre en otros argumentos como en los gradientes con colores en rgba o en toggle con variables toggle(var(a),var(b),var(c)). Por ejemplo.
Ejemplo de la regla @if con la mínima expresión lógica
El caso más sencillo de regla @if sería aquel que sólo evalúa una condición para un solo selector. Esto es, su expresión lógica sólo tiene un argumento:
@if (.post-1 img:nth-of-type(1) (width >= 800px)) {
.post-1 img:nth-of-type(1) {
float: none;
clear: both;
display: block;
margin: 1rem auto;
/* No permitido declarar la misma propiedad
usada en el argumento: Dependencia circular */
}
.post-1 {
width: auto;
float: none;
margin-right: 0;
}
nav li {
display: inline-block;
}
}
Expresión lógica compleja en la regla @if
A modo y semejanza de lo que ocurre con otras at rules (como las medias queries) en la expresión lógica de la regla @if se podrá evaluar más de una comparación lógica. Dos son los casos:
- Un único selector con varias comparaciones lógicas. La expresión lógica estará formada por un argumento único complejo.
- Evaluar más de un selector. Tendríamos una expresión lógica (compleja) formada por múltiples argumentos.
En ambos casos, en el argumento único complejo o múltiples argumentos, cada uno de sus valores podrá ser una lista de ellos separados por comas |,| o estar enlazados por los operadores lógicos |not| y |and|
Argumento único complejo
Evaluamos en el mismo y único selector varias condiciones, sean de la misma o distinta propiedad.
@if (.mi_lista (height >= 10rem) and (display == block)) {
/* reglas */
}
Múltiples argumentos
En este segundo caso se avalúan varios selectores distintos, cada uno con sus condiciones lógicas:
@if (.mi_lista (height >= 10rem)),
(.otro (width < 300px)) and
(.beta ()) {
/* reglas */
}
En este último ejemplo se contempla la mera existencia en el html del elemento con clase 'beta' indicada por la comparación lógica vacía.
¿En el caso de evaluase la misma condición lógica (sencilla o múltiple) para varios selectores podrían incluirse todos ellos en un argumento único separados por comas y/o los operadores not/and tal como sucede en los selectores múltiples de las reglas normales en Css?
@if (.mi_lista, .otro (height >= 10rem) not (display == none)) {
/* reglas */
}
¿O sería más apropiado conformar múltiples argumentos como en el ejemplo anterior?
Conflictos y no permitido
El primer conflicto, y por lo tanto no permitido y que daría lugar a invalidad la regla @if, serían las dependencias circulares o recursividad entre la condición lógica de la expresión y el contenido en el bloque de reglas. Un ejemplo sería evaluar el tamaño de un elemento (width/height) relativa a su ancestro en la condición lógica e incluir una declaración para esta misma propiedad de su ancestro en el set de reglas.
Tu opinión al respecto
Como te decía al inicio me gustaría saber tu opinión, sea cual sea y sobre el aspecto que creas conveniente. Quizás si entre todos pulimos lo suficiente la idea de la regla @if en Css la veamos algún día entre los documentos de trabajo del consorcio :-))
Kseso
the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso
El mayor problema que tiene esto es el mismo que el de la proposición de las "element media queries", que eran algo del estilo a:
ResponderEliminar.content (max-width: 15px) {
/* propiedades */
}
y es (entre otros) que da lugar a recursividad infinita:
.content (max-width: 800px) {
width: 900px; /* Ala, ahora qué? */
}
Es un ejemplo muy vasto, pero bueno... tab atkins lo explica mejor (http://www.xanthir.com/b4PR0)
Como idea, está bien. Ahora, viable no creo que sea...
La principal diferencia es que en la propuesta de 'element media query' se toman valores leídos de elementos, en '@if' serían solamente valores declarados en sus mismas reglas.
EliminarEsto limita muchas expectativas a futuro sobre el uso de un CSS que "lea" más cambios desde el usuario, pero es práctico si nos atenemos a la aplicación de "la última regla".
En un caso como
@if (.post-1 img:nth-of-type(1) (width >= 800px)) {
.post-1 img:nth-of-type(1) {
float: none;
clear: both;
display: block;
margin: 1rem auto;
width: 900px;
}
}
después de ver que la primera imagen tiene un ancho mayor que 800px, se le aplica un ancho de 900px. Y el CSS ya no lo vuelve a leer; ahí se muere. Para los porcentajes que se ajustan con resize, la lectura se hace al terminar con la redimensión, si se cumple con la regla se aplica el formato; y no se vuelve a leer hasta que terminen de redimensionar o recargar alguna próxima vez.
Por supuesto que prohibir reglas conflictivas entre sí (vale el aviso de "/* No permitido declarar la misma propiedad usada en el argumento: Dependencia circular */") también sirve, pero ya es más difícil de implementar.
Gracias por la opinión, Emilio y Furoya
EliminarSí, efectivamente, el tema de las dependencias circulares es una cuestión no menor a tener en cuenta.
De hecho ya lo tenía en mente antes de ponerme a escribir el artículo, pues fue una cuestión que inmediatamente surgió al conversar con @tabatkins ,vía twitter,
De ahí que sea un punto que está recogido en el apartado Conflictos y no permitido
Furoya Ese sólo es un comentario css al código de ejemplo. Veo que mal puesto pues te he inducido a error.
No pretendía indicar que el navegador tuviese que lanzar una advertencia (¿cuándo, a quién y visible para quién?) de error ni mucho menos. Ese no es su cometido xD
Un saludo
Noooo! XD XD XD
EliminarEstá bien, sí había entendido, lo que pasa es que me resultó gracioso justamente porque la única manera de que eso funcione es que se lo recomiende en los estándares de forma escrita y explícita, y aún así ya sabemos que los chapuceros los ignoran, hacen una referencia circular en su página y después están preguntando en foros y blogs y comunidades «por qué no funciona».
Pero justamente, lo que no sé si expliqué bien en el comentario anterior es que '@if' no debería tener esa limitación. CSS tiene una prticularidad : monitorea el documento todo el tiempo, y ante cualquier cambio aplica sus reglas; por eso en una mediaquery la objeción es pertinente.
Pero un condicional debe tener lógica de programación, de ahí viene el "if". Y en programación los cambios se disparan en un caso determinado (un nombre común es "evento") y después no más. Por eso no puede existir ese loop infinito o incoherente al aplicar un formato.
El problema que aparece ahora es que hay que ponerse de acuerdo en qué "eventos" por omisión van a ejecutar los "if". Claramente un "load", porque la comparación se hará después de cargar todo el documento. Pero habría que agregar un "resize", para que vuelva a aplicar formatos al terminar de redimensionar la página o un elemento de ella. También podría ser un "scroll".
O podrían agregarse junto a los operadores, para que el desarrollador elija los casoso. Si le pone un ":scroll" y no un ":resize" el cambio ocurrirá al desplazar pero no al cambiar de tamaño. Algo que no tiene mucho sentido, pero ya que estamos proponiendo ...