Frontal avanzado y assetic
-
Upload
miquel-company-rodriguez -
Category
Technology
-
view
1.550 -
download
4
description
Transcript of Frontal avanzado y assetic
¿Quién Soy?
•Tech Lead en Ofertix.com•Apasionado de la Web•7 años en PHP•Enganchado a Symfony desde la 1.2•‘Whovian’ y Aerotrastornado
[email protected]@solilokiamhttp://www.github.com/solilokiam
¿Qué es Ofertix?
¿Qué es Ofertix?
•Vendemos productos y servicios por internet
¿Qué es Ofertix?
•Vendemos productos y servicios por internet•A precios interesantes
¿Qué es Ofertix?
•Vendemos productos y servicios por internet•A precios interesantes•Tenemos varias lineas de negocio
¿Qué es Ofertix?
•Vendemos productos y servicios por internet•A precios interesantes•Tenemos varias lineas de negocio•Ventas Privadas, Ocio, Full Price y Tienda Física
¿Qué es Ofertix?
•Vendemos productos y servicios por internet•A precios interesantes•Tenemos varias lineas de negocio•Ventas Privadas, Ocio, Full Price y Tienda Física•7 años en marcha
¿Qué es Ofertix?
•Vendemos productos y servicios por internet•A precios interesantes•Tenemos varias lineas de negocio•Ventas Privadas, Ocio, Full Price y Tienda Física•7 años en marcha•Principalmente Symfony 1.2
¿Que Problemas Tenemos?
¿Que Problemas Tenemos?
NINGUNO. SOMOS LOS MEJORES
¿Que Problemas Tenemos?
NINGUNO. SOMOS LOS MEJORES
http://miexesunameme.blogspot.com.es/2013/05/mientras-tanto-en-clase.html
Pero...
Pero...
•Nuestra interfaz móvil es mejorable
Pero...
•Nuestra interfaz móvil es mejorable•Queremos añadir full-text search
Pero...
•Nuestra interfaz móvil es mejorable•Queremos añadir full-text search•Queremos mejorar lineas de negocio
Pero...
•Nuestra interfaz móvil es mejorable•Queremos añadir full-text search•Queremos mejorar lineas de negocio•Ya toca un lavado de cara
Pero...
•Nuestra interfaz móvil es mejorable•Queremos añadir full-text search•Queremos mejorar lineas de negocio•Ya toca un lavado de cara•Y de cuerpo
http://www.youtube.com/watch?v=PDXrXBsTFSE
Solución
http://symfony.com/logo
Solución
Re-escribir el frontal de todos nuestros sites.
http://symfony.com/logo
Solución
Re-escribir el frontal de todos nuestros sites.
Aplicando lo aprendido de nuestros errores
http://symfony.com/logo
Solución
http://symfony.com/logo
La remodelación del site tiene muchos temas interesantes
•Cache•Reverse Proxy•No-SQL•Full-text Search•UX•Gestión de sesiones•Recolección de datos•Big Data
•Socialización•Web Services•Javascript Avanzado (MVC)•Gestión de Statics•Colas•Optimización de Carga•Balanceo de pagos•...
Pero hoy toca...
Pero hoy toca...
Mobile y otros dispositivos
¿Por qué?
Fuente Google Analytics 04/06/2013
¿Por qué?Otros
6%Android Browser
11%
Safari IOS 16%
Safari Mac4%Firefox Windows
13%
IE Explorer23%
Chrome Windows27%
Fuente Google Analytics 04/06/2013
Dos posibles soluciones
http://www.webdesignshock.com/responsive-design/http://www.betsmartmedia.com/wp-content/themes/scope/images/svg/fallback/iphone.png
Dos posibles soluciones
http://www.webdesignshock.com/responsive-design/http://www.betsmartmedia.com/wp-content/themes/scope/images/svg/fallback/iphone.png
Mobile Site
Dos posibles soluciones
http://www.webdesignshock.com/responsive-design/http://www.betsmartmedia.com/wp-content/themes/scope/images/svg/fallback/iphone.png
Responsive Design
Mobile Site
Mobile Design
Mobile DesignDevice Centric Design
•Una plantilla por tipo de device a cubrir.•Una hoja de estilos por device*•Un “Javascript” por device*•Detectamos el tipo de device al servir el site•Permitimos cambiar el tipo de plantilla servida.
Mobile DesignDevice Centric Design
Como lo hacemos
<?phpnamespace Solilokiam\RequestListenerBundle\EventListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Solilokiam\RequestListenerBundle\Detector\DeviceDetector;
class RequestListener{ public function onKernelRequest(GetResponseEvent $eve
nt)
{ $detector = new DeviceDetector();
$request = $event->getRequest();
$user_agent = $request->headers->get('user-agent');
if($detector->isMobile($user_agent))
{ $request->setRequestFormat('mobile', 'text/ht
ml');
} elseif($detector->isGameConsole($user_agent)) {
$request->setRequestFormat('game', 'text/html');
} elseif($detector->isTv($user_agent)) {
$request->setRequestFormat('tv', 'text/html');
} else { $request->setRequestFormat('html', 'text/html
');
} }}
<?phpnamespace Solilokiam\RequestListenerBundle\Detector;
class DeviceDetector{ //Incomplete regexs just educational purpouse;
private $mobile_device_regex = '/(alcatel|amoi|android|avantgo|blackberry|benq|cell|cricket|docomo|elaine|htc|iemobile|iphone|ipad|ipaq|ipod|j2me|java|midp|mini|mmp|mobi|motorola|nec-|nokia|palm|panasonic|philips|phone|playbook|sagem|sharp|sie-|silk|smartphone|sony|symbian|t-mobile|telus|up\.browser|up\.link|vodafone|wap|webos|wireless|xda|xoom|zte)/i'; private $game_console_device_regex = '/xbox/i'; private $tv_device_regex = '/(bravia|googletv)/i';
public function __construct() {
}
public function isMobile($user_agent) { if(preg_match($this->mobile_device_regex,$user_agent)) { return true; } else { return false; } }
public function isGameConsole($user_agent) { if(preg_match($this->game_console_device_regex,$user_agent)) { return true; } else { return false; } }
public function isTv($user_agent) { if(preg_match($this->tv_device_regex,$user_agent)) { return true; } else { return false; } }}
Como lo hacemos
parameters: solilokiam_request_listener.example.class: Solilokiam\RequestListenerBundle\EventListener\RequestListenerservices: solilokiam_request_listener.example: class: %solilokiam_request_listener.example.class% tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
<?php
namespace Solilokiam\FrontBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{ public function indexAction($name)
{ $format = $this->getRequest()->getRequestFormat()
;
return $this->render('SolilokiamFrontBundle:Default:index.'.
$format.'.twig', array('name' => $name));
}}
Como lo hacemos
Buscamos Programadores
http://alba-twist.blogspot.com.es/2011_10_01_archive.html
Buscamos Programadores
•Expertos en Symfony 2 y 1•Motivados•Con ganas de aprender y mejorar
•Incorporarse en un gran equipo•Proyecto consolidado pero en mejora continua•Buenas condiciones
Más Información: [email protected]
http://alba-twist.blogspot.com.es/2011_10_01_archive.html
<?phpnamespace Solilokiam\RequestListenerBundle\EventListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;use Symfony\Component\HttpKernel\Event\GetResponseEvent;use Symfony\Component\HttpKernel\HttpKernel;use Solilokiam\RequestListenerBundle\Manager\DeviceRedirectManager;use Solilokiam\RequestListenerBundle\Manager\DeviceManager;
class RequestListener{ protected $device_manager; protected $redirect_manager;
public function __construct(DeviceManager $device_manager,DeviceRedirectManager $redirect_manager) { $this->device_manager = $device_manager; $this->redirect_manager = $redirect_manager; }
public function onKernelRequest(GetResponseEvent $event) { if(HttpKernel::MASTER_REQUEST === $event->getRequestType()) { $request = $event->getRequest(); $user_agent = $request->headers->get('user-agent');
$this->device_manager->detectDevice($user_agent);
$response = $this->redirect_manager->redirectIfNeeded($request);
if($response) $event->setResponse($response);
return; } }}
Como lo hacemos (pero mejor)
Como lo hacemos (pero mejor)
<?phpnamespace Solilokiam\RequestListenerBundle\Manager;
use Solilokiam\RequestListenerBundle\Detector\DeviceDetector;
class DeviceManager{ const DEVICE_MOBILE = 'mobile'; const DEVICE_GAME = 'game'; const DEVICE_TV = 'tv';
protected $session;
public function __construct($session) { $this->session = $session; }
public function hasDevice() { return $this->session->has('device'); }
public function setDevice($device) { $this->session->set('device',$device); }
public function getDevice() { return $this->session->get('device'); }
public function detectDevice($user_agent)
{ $detector = new DeviceDetector();
if($detector->isMobile($user_agent))
{ $this->setDevice(self::DEVICE_MOBILE);
} elseif($detector->isGameConsole($user_agent)) {
$this->setDevice(self::DEVICE_GAME);
} elseif($detector->isTv($user_agent)) {
$this->setDevice(self::DEVICE_TV);
} }}
<?phpnamespace Solilokiam\RequestListenerBundle\Manager;
//use \Solilokiam\RequestListenerBundle\Manager\DeviceManager;use Symfony\Component\HttpFoundation\RedirectResponse;
class DeviceRedirectManager{ const VIEW_MOBILE = 'mobile.desymfony.local'; const VIEW_GAME = 'game.desymfony.local'; const VIEW_TV = 'tv.desymfony.local';
protected $view_type; protected $device_manager;
public function __construct(DeviceManager $manager) { $this->device_manager = $manager;
if(!$this->device_manager->hasDevice()) { $this->view_type = ''; } else { $device = $this->device_manager->getDevice();
$this->view_type = $device; } }
public function redirectIfNeeded($request) { $host = $request->getHost();
$responseUrl = null;
Como lo hacemos (pero mejor)
$this->view_type = $device; } }
public function redirectIfNeeded($request) { $host = $request->getHost();
$responseUrl = null;
if($host != self::VIEW_MOBILE && $this->view_type == 'mobile') { $responseUrl = $this->generateRedirectUrl($request,self::VIEW_MOBILE); }
if($host != self::VIEW_GAME && $this->view_type == 'game') { $responseUrl = $this->generateRedirectUrl($request,self::VIEW_GAME); }
if($host != self::VIEW_TV && $this->view_type == 'tv') { $responseUrl = $this->generateRedirectUrl($request,self::VIEW_TV); }
if($responseUrl !== null) { return new RedirectResponse($responseUrl); } return null; }
public function generateRedirectUrl($request,$view) { return 'http://'.$view.$request->getRequestUri(); }
}
Como lo hacemos (pero mejor)
<?phpnamespace Solilokiam\RequestListenerBundle\Twig;
use Symfony\Bundle\TwigBundle\TwigEngine as BaseTwigEngine;use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables;use Symfony\Component\Templating\TemplateNameParserInterface;use Symfony\Component\Config\FileLocatorInterface;use Solilokiam\RequestListenerBundle\Manager\DeviceManager;
class TwigEngine extends BaseTwigEngine{ protected $device_manager;
public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator, DeviceManager $device_manager) { $this->device_manager = $device_manager;
parent::__construct($environment, $parser, $locator); }
public function render($name, array $parameters = array()) { $device = $this->device_manager->getDevice();
$device_template = preg_replace("/^\w+:\w+:/", '$0'.$device.'/', $name); if ($this->exists($device_template)) { $name = $device_template; }
return parent::render($name, $parameters); }}
Como lo hacemos (pero mejor)
Como lo hacemos (pero mejor)
<?php
namespace Solilokiam\FrontBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller{ public function indexAction($name) { return $this->render('SolilokiamFrontBundle:Default:index.html.twig', array('name' => $name)); }}
Misión cumplida
http://www.vayagif.com/169459/claro-que-si-campeon-michael-jackson-estaria-orgulloso-de-ti
Misión cumplida
•Faltaría switch entre vistas•Mejor por cookies que por sesión•URL’s y otras cosas configurables
http://www.vayagif.com/169459/claro-que-si-campeon-michael-jackson-estaria-orgulloso-de-ti
Misión cumplida
•Faltaría switch entre vistas•Mejor por cookies que por sesión•URL’s y otras cosas configurables
https://github.com/kbond/ZenstruckMobileBundlehttps://github.com/suncat2000/MobileDetectBundle
http://www.vayagif.com/169459/claro-que-si-campeon-michael-jackson-estaria-orgulloso-de-ti
Ventajas
•Se ajusta mejor a las necesidades•Facilidad de cambiar/hacer cosas especiales•Más óptimo
Inconvenientes
•Mucho trabajo.•Alta posibilidad de liarla parda.•Múltiples url’s para la misma cosa
Responsive Design
•Una plantilla para todos los devices•Una sola hoja de estilos•Un solo javascript*•La presentación se adapta al dispositivo•Soporte a tantos devices como quieras*
¿Qué es Responsive Design?
Responsive Web design is the approach that suggests that design and development should respond to the user’s behavior and environment based on screen size, platform and orientation.
Kayla Knight @KaylaMaeKnight
Los 3 pilares del Responsive Design
Los 3 pilares del Responsive Design
1.Layout basado en un grid flexible
Los 3 pilares del Responsive Design
1.Layout basado en un grid flexible2.Imágenes y media flexibles
Los 3 pilares del Responsive Design
1.Layout basado en un grid flexible2.Imágenes y media flexibles3.Media Queries
Layout basado en un grid flexible
page { margin: 36px auto; width: 970px;}.blog { margin: 21px 0 0 0; width: 970px;}.blog .main { float: left; padding: 17px;
width: 678px;}.blog .other { float: right;margin: 0 21px 0 0;
width: 271px;}
Normas Básicas
Ningún tamaño fijado.Todo Relativo
•Width x Height•Padding•Margin•Font-Size•...
Regla de Cálculo
objetivo / contexto * 100 = resultado%
objetivo / contexto
.blog .main { float: left; padding: 17px;
width: 678px;}
Un Cálculo de Ejemplo
.blog .main { float: left; padding: 17px;
width: 678px;}
678 / 970 * 100 = 69,896907216495
Un Cálculo de Ejemplo
.blog .main { float: left; padding: 17px;
width: 678px;}
678 / 970 * 100 = 69,896907216495
Un Cálculo de Ejemplo
17 / 970 * 100 = 1,752577319588
678 / 970 * 100 = 69,896907216495
Un Cálculo de Ejemplo
17 / 970 * 100 = 1,752577319588
.blog .main { float: left;
padding: 69,896907216495%; width: 1,752577319588%;}
¿Y qué pasa con la tipografia?
Aplicamos la misma regla de cálculo
h1 { font-size: 24px;}h1 a { font-size: 11px;}
24 / context = ¿?
11/ context = ¿?
¿Y qué pasa con la tipografia?
El tamaño por defecto de la fuente suele ser 16px
¿Y qué pasa con la tipografia?
El tamaño por defecto de la fuente suele ser 16px
Mejor lo seteamos en nuestro fichero de reset
¿Y qué pasa con la tipografia?
El tamaño por defecto de la fuente suele ser 16px
body{font-size:16px;
}
Mejor lo seteamos en nuestro fichero de reset
¿Y qué pasa con la tipografia?
El tamaño por defecto de la fuente suele ser 16px
body{font-size:16px;
}
Mejor lo seteamos en nuestro fichero de reset
body{font-size: 100%;
}
¿Y qué pasa con la tipografia?
El tamaño por defecto de la fuente suele ser 16px
body{font-size:16px;
}
Mejor lo seteamos en nuestro fichero de reset
body{font-size: 100%;
}
http://meyerweb.com/eric/tools/css/reset/
¿Y qué pasa con la tipografia?
Aplicamos la misma regla de calculo
h1 { font-size: 24px;}h1 a { font-size: 11px;}
¿Y qué pasa con la tipografia?
Aplicamos la misma regla de calculo
h1 { font-size: 24px;}h1 a { font-size: 11px;}
24 / 16 = 1.5
¿Y qué pasa con la tipografia?
Aplicamos la misma regla de calculo
h1 { font-size: 24px;}h1 a { font-size: 11px;}
24 / 16 = 1.5
11/ 16 = 0,6875
¿Y qué pasa con la tipografia?
Aplicamos la misma regla de calculo
24 / 16 = 1.5
11/ 16 = 0,6875
h1 { font-size: 1.5em;}h1 a { font-size: 0.6875em;}
Imágenes y media flexibles
Varias Opciones:•Resize•Crop•HTML5 picture tag•Clown Car
Resize
img { max-width: 100%;}
Resize
img,embed,object,video { max-width: 100%;}
Resize
img,embed,object,video { max-width: 100%;}
•La solución más compatible•Ancho de Banda Poco Optimo•Renderizado en navegador poco optimo
Crop
.img_container { overflow: hidden;}.img_container img { display: block; max-width: auto;}
•Igual de compatible que resize•La imagen queda cortada•Ancho de banda poco optimo•Renderizado no excesivamente malo
HTML5 picture tag
<picture alt="Description of image subject."> <source srcset="small.jpg 1x, small-highres.jpg 2x"> <source media="(min-width: 18em)" srcset="med.jpg 1x, med-highres.jpg 2x"><source media="(min-width: 45em)" srcset="large.jpg 1x, large-highres.jpg 2x"> <img src="small.jpg" alt="Description of image subject."> </picture>
•Soporte Webkit (aunque con fallback)•Muy bueno con el ancho de banda•Muy bueno con el navegador
Clown Car<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 329" preserveAspectRatio="xMidYMid meet"><title>Clown Car Technique</title><style>svg { background-size: 100% 100%; background-repeat: no-repeat;}@media screen and (max-width: 400px) { svg { background-image: url(images/small.png"); }}@media screen and (min-width: 401px) and (max-width: 700px) { svg { background-image: url(images/medium.png); }}@media screen and (min-width: 701px) and (max-width: 1000px) { svg { background-image: url(images/big.png); }}@media screen and (min-width: 1001px) { svg { background-image: url(images/huge.png); }}</style></svg>
Clown Car<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 329" preserveAspectRatio="xMidYMid meet"><title>Clown Car Technique</title><style>svg { background-size: 100% 100%; background-repeat: no-repeat;}@media screen and (max-width: 400px) { svg { background-image: url(images/small.png"); }}@media screen and (min-width: 401px) and (max-width: 700px) { svg { background-image: url(images/medium.png); }}@media screen and (min-width: 701px) and (max-width: 1000px) { svg { background-image: url(images/big.png); }}@media screen and (min-width: 1001px) { svg { background-image: url(images/huge.png); }}</style></svg>
•Buen soporte•Buena con el ancho de banda•Buena con el navegador•Requiere de trabajo en el servidor
Media Queries
Desarrollado a partir de los Media Types (CSS 2)
@media screen { body { font-size: 100%; }}@media print { body { font-size: 15pt; }}
Media Queries
@media screen and (min-width: 1024px) { body { font-size: 100%; }}
<link rel="stylesheet" href="wide.css" media="screen and (min-width: 1024px)" />
Media Queries
No solamente podemos filtrar por height o width:
widthheightdevice-widthdevice-heightorientationaspect ratio
color (bit number)color-indexmonochrome(bits x pixel)resolution (dpi)scan(tv progressive o scan)grid
Media Queries
No solamente podemos filtrar por height o width:
widthheightdevice-widthdevice-heightorientationaspect ratio
color (bit number)color-indexmonochrome(bits x pixel)resolution (dpi)scan(tv progressive o scan)grid
@media screen and (min-device-width: 480px) and (orientation: landscape) { ... }
Media Queries
Arreglar todas las cosas que no se acaban de adaptar con Layout basado en un grid flexible
Media Queries
Arreglar todas las cosas que no se acaban de adaptar con Layout basado en un grid flexible
Cambiar tipografiasModificar layout
Mostrar / Ocultar elementos...
Ventajas
•Menos trabajo de crear vistas•Menos posibilidad de liarla•Mejor adaptabilidad ante nuevos devices•Mejor SEO
Inconvenientes
•Mucho trabajo al maquetar•No muy óptimo
http://www.youtube.com/watch?v=pDUH1Pjl5Sk
http://www.abookapart.com/products/responsive-web-designhttp://www.youtube.com/watch?v=pDUH1Pjl5Sk
http://www.abookapart.com/products/responsive-web-designhttp://www.youtube.com/watch?v=pDUH1Pjl5Sk
http://twitter.github.io/bootstrap/
http://foundation.zurb.com/
http://www.getskeleton.com/
Preprocesadores CSS
•Ahorro de muchas horas de maquetación•Cambios Rápidos•Código Estructurado
Assetic los integra perfectamente en nuestros proyectos.
Instalar nodeJS + npm$ npm install less
Symfony
Instalar nodeJS + npm$ npm install less
assetic: filters: cssrewrite: ~ less: node: /usr/local/bin/node node_paths: [/usr/local/lib/node_modules]
Symfony
Instalar nodeJS + npm$ npm install less
assetic: filters: cssrewrite: ~ less: node: /usr/local/bin/node node_paths: [/usr/local/lib/node_modules]
{% block stylesheets %}{% stylesheets 'less/main.less' filter='less' output='css/main.css'%}<link rel="stylesheet" href="{{ asset_url }}">{% endstylesheets %}
Symfony
assetic: filters: cssrewrite: ~ less: node: /usr/local/bin/node node_paths: [/usr/local/lib/node_modules] yui_css: jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar"
Symfony
assetic: filters: cssrewrite: ~ less: node: /usr/local/bin/node node_paths: [/usr/local/lib/node_modules] yui_css: jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar"
{% block stylesheets %}{% stylesheets 'less/main.less' filter='less,?yui_css’ output='css/main.css'%}<link rel="stylesheet" href="{{ asset_url }}">{% endstylesheets %}
Symfony
./app/console assetic:dump --env=prod --no-debug
Symfony
Variables
@azul: #5B83AD;@azul-claro: (@azul + #111);
#header { color: @azul-claro; }
Variables
@azul: #5B83AD;@azul-claro: (@azul + #111);
#header { color: @azul-claro; }
#header { color: #6c94be; }
Variables
@azul: #5B83AD;@azul-claro: (@azul + #111);
#header { color: @azul-claro; }
#header { color: #6c94be; }
•Scope de las variables igual que CSS•No han de ser declaradas antes de ser utilizadas
Variables
@azul: #5B83AD;@azul-claro: (@azul + #111);
#header { color: @azul-claro; }
#header { color: #6c94be; }
•Scope de las variables igual que CSS•No han de ser declaradas antes de ser utilizadas
@less-mola: "Less Mola";@var: 'less-mola';content: @@var;
Variables
@azul: #5B83AD;@azul-claro: (@azul + #111);
#header { color: @azul-claro; }
#header { color: #6c94be; }
•Scope de las variables igual que CSS•No han de ser declaradas antes de ser utilizadas
@less-mola: "Less Mola";@var: 'less-mola';content: @@var;
content: "Less Mola";
Mixins
.bordered { border-top: dotted 1px black; border-bottom: solid 2px black;}#menu a { color: #111; .bordered;}
Mixins
.bordered { border-top: dotted 1px black; border-bottom: solid 2px black;}#menu a { color: #111; .bordered;}
#menu a { color: #111; border-top: dotted 1px black; border-bottom: solid 2px black;}
Mixins
.bordered { border-top: dotted 1px black; border-bottom: solid 2px black;}#menu a { color: #111; .bordered;}
#menu a { color: #111; border-top: dotted 1px black; border-bottom: solid 2px black;}
.border-radius (@radius: 5px) { border-radius: @radius; -moz-border-radius: @radius; -webkit-border-radius: @radius;}#header { .border-radius(4px);}.button { .border-radius;}
Mixins
.bordered { border-top: dotted 1px black; border-bottom: solid 2px black;}#menu a { color: #111; .bordered;}
#menu a { color: #111; border-top: dotted 1px black; border-bottom: solid 2px black;}
.border-radius (@radius: 5px) { border-radius: @radius; -moz-border-radius: @radius; -webkit-border-radius: @radius;}#header { .border-radius(4px);}.button { .border-radius;}
#header{ border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px;}
.button { border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;}
Mixins
Multiples Parametros separados por semicolon
Mixins
Multiples Parametros separados por semicolon
Less permite sobrecarga en los mixins
Mixins
Multiples Parametros separados por semicolon
Less permite sobrecarga en los mixins
.test_mixin(@width) { width: @width;}.test_mixin(@width; @color:#000000) { width-2: @width; color: @padding;}.test_mixin(@width; @color; @margin: 2) { width-3: @color; color-3: @padding; margin: @margin @margin @margin @margin;}.test div { .test_mixin(15px);}
Mixins
Multiples Parametros separados por semicolon
Less permite sobrecarga en los mixins
.test_mixin(@width) { width: @width;}.test_mixin(@width; @color:#000000) { width-2: @width; color: @padding;}.test_mixin(@width; @color; @margin: 2) { width-3: @color; color-3: @padding; margin: @margin @margin @margin @margin;}.test div { .test_mixin(15px);}
.test div { width: 15px; width-2: 15px; color: #000000;}
Mixins
.margin_mixin(@top; @right; @down; @left) { margin: @arguments;}.margin_mixin(2px; 5px;2px;5px);
Mixins
.margin_mixin(@top; @right; @down; @left) { margin: @arguments;}.margin_mixin(2px; 5px;2px;5px);
margin: 2px 5px 2px 5px;
!important
.test_mixin (@a: 0) { margin: @a; padding: @a;}.no_importante { .test_mixin(1); }.muy_importante { .test_mixin(2) !important; }
!important
.test_mixin (@a: 0) { margin: @a; padding: @a;}.no_importante { .test_mixin(1); }.muy_importante { .test_mixin(2) !important; }
.no_importante { margin: 1px; padding: 1px;}.muy_importante { margin: 2px !important; padding: 2px !important;}
Nested Rules
#header { color: black; }#header .navigation { font-size: 12px;}#header .logo { width: 300px;}#header .logo:hover { text-decoration: none;}
Nested Rules
#header { color: black; }#header .navigation { font-size: 12px;}#header .logo { width: 300px;}#header .logo:hover { text-decoration: none;}
#header { color: black; .navigation { font-size: 12px } .logo { width: 300px; &:hover { text-decoration: none } }}
Operations
•Afectan a numeros y colores•Tienen que ir entre paréntesis
Operations
•Afectan a numeros y colores•Tienen que ir entre paréntesis@context: 970
.blog .main { float: left;padding: percentage((679px / @context));
width: percentage((17px / @context));
}
Operations
•Afectan a numeros y colores•Tienen que ir entre paréntesis@context: 970
.blog .main { float: left;padding: percentage((679px / @context));
width: percentage((17px / @context));
}
.blog .main { float: left;
padding: 69,896907216495%; width: 1,752577319588%;}
Importing
@import "test.css";
Importing
@import "test.css"; @import "library.less";
Importing
@import "test.css"; @import "library.less";
@imported-color: red;h1 { color: green; }
@import "library.less" screen and (max-width: 400px);@import "library.less";
.class { color: @importedColor;}
Importing
@import "test.css"; @import "library.less";
@imported-color: red;h1 { color: green; }
@import "library.less" screen and (max-width: 400px);@import "library.less";
.class { color: @importedColor;}
@media screen and (max-width: 400px) { h1 { color: green; }}
h1 { color: green; }.class { // Use imported variable color: #ff0000;}
Funciones
escape(@string); // URL encodes a stringe(@string); // escape string content%(@string, values...); // formats a string
ceil(@number); // rounds up to an integerfloor(@number); // rounds down to an integerpercentage(@number); // converts to a %, e.g. 0.5 -> 50%round(number, [places: 0]);// rounds a number to a number of places
saturate(@color, 10%); // return a color 10% points *more* saturated
desaturate(@color, 10%);// return a color 10% points *less* saturated
lighten(@color, 10%); // return a color 10% points *lighter*
darken(@color, 10%); // return a color 10% points *darker*
Pattern Matching
.mixin (dark; @color) { color: darken(@color, 10%);}.mixin (light; @color) { color: lighten(@color, 10%);}.mixin (@_; @color) { display: block;}
Pattern Matching
.mixin (dark; @color) { color: darken(@color, 10%);}.mixin (light; @color) { color: lighten(@color, 10%);}.mixin (@_; @color) { display: block;}
@switch: light;
.class { .mixin(@switch; #888);}
Pattern Matching
.mixin (dark; @color) { color: darken(@color, 10%);}.mixin (light; @color) { color: lighten(@color, 10%);}.mixin (@_; @color) { display: block;}
@switch: light;
.class { .mixin(@switch; #888);}
.class { color: #a2a2a2; display: block;}
Guarded Params
.mixin (@a) when (lightness(@a) >= 50%) { background-color: black;}.mixin (@a) when (lightness(@a) < 50%) { background-color: white;}.mixin (@a) { color: @a;}
Guarded Params
.mixin (@a) when (lightness(@a) >= 50%) { background-color: black;}.mixin (@a) when (lightness(@a) < 50%) { background-color: white;}.mixin (@a) { color: @a;}
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }
Guarded Params
.mixin (@a) when (lightness(@a) >= 50%) { background-color: black;}.mixin (@a) when (lightness(@a) < 50%) { background-color: white;}.mixin (@a) { color: @a;}
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }
.class1 { background-color: black; color: #ddd;}.class2 { background-color: white; color: #555;}
Comentarios
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
Comentarios
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
Comentarios
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
//Hola soy un comentario que mejor no salga en produccion.test_class { color: #008866 }
Comentarios
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
/* Hola soy un comentario la mar de interesante */.test_class { color: #008866 }
//Hola soy un comentario que mejor no salga en produccion.test_class { color: #008866 }
.test_class { color: #008866 }
Quiero saber más.
http://lesscss.org http://twitter.github.io/bootstrap/
http://lesshat.com/
Quiero saber más.
http://lesscss.org http://twitter.github.io/bootstrap/
http://lesshat.com/
¿Qué pasa con SASS?
Quiero saber más.
http://lesscss.org http://twitter.github.io/bootstrap/
http://lesshat.com/
¿Qué pasa con SASS?
•Más completo que less•Peor documentación•Mismos principios•Hecho en ruby•Ultimamente menos activo
Quiero saber más.
http://lesscss.org http://twitter.github.io/bootstrap/
http://lesshat.com/
¿Qué pasa con SASS?
•Más completo que less•Peor documentación•Mismos principios•Hecho en ruby•Ultimamente menos activo
http://sass-lang.com/
http://compass-style.org/
http://foundation.zurb.com/
Resumiendo
•Adaptad vuestra aplicación a varios devices•Analizad vuestras necesidades•Aplicad la técnica que mejor os vaya•Utilizad preprocesadores de CSS
Preguntas y respuestas
https://www.youtube.com/watch?v=Q1AZfqghL30