SlideShare uma empresa Scribd logo
1 de 159
Baixar para ler offline
¿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
miquel@solilokiam.com
@solilokiam
http://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 yTienda Física
¿Qué es Ofertix?
•Vendemos productos y servicios por internet
•A precios interesantes
•Tenemos varias lineas de negocio
•Ventas Privadas, Ocio, Full Price yTienda 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 yTienda 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 Mac
4%
Firefox Windows
13%
IE Explorer
23%
Chrome Windows
27%
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
<?php
namespace SolilokiamRequestListenerBundleEventListener;
use SymfonyComponentHttpKernelHttpKernelInterface;
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SolilokiamRequestListenerBundleDetectorDeviceDetector;
class RequestListener
{
public function onKernelRequest(GetResponseEvent $event)
{
$detector = new DeviceDetector();
$request = $event->getRequest();
$user_agent = $request->headers->get('user-agent');
if($detector->isMobile($user_agent))
{
$request->setRequestFormat('mobile', 'text/html');
} 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');
}
}
}
<?php
namespace SolilokiamRequestListenerBundleDetector;
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: SolilokiamRequestListenerBundleEventListenerRequestListener
services:
solilokiam_request_listener.example:
class: %solilokiam_request_listener.example.class%
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
<?php
namespace SolilokiamFrontBundleController;
use SymfonyBundleFrameworkBundleControllerController;
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: it@ofertix.com
http://alba-twist.blogspot.com.es/2011_10_01_archive.html
<?php
namespace SolilokiamRequestListenerBundleEventListener;
use SymfonyComponentHttpKernelHttpKernelInterface;
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentHttpKernelHttpKernel;
use SolilokiamRequestListenerBundleManagerDeviceRedirectManager;use SolilokiamRequestListenerBundleManagerDeviceManager;
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)
<?php
namespace SolilokiamRequestListenerBundleManager;
use SolilokiamRequestListenerBundleDetectorDeviceDetector;
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);
}
}
}
<?php
namespace SolilokiamRequestListenerBundleManager;
//use SolilokiamRequestListenerBundleManagerDeviceManager;use SymfonyComponentHttpFoundationRedirectResponse;
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();
Como lo hacemos (pero mejor)
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)
<?php
namespace SolilokiamRequestListenerBundleTwig;
use SymfonyBundleTwigBundleTwigEngine as BaseTwigEngine;
use SymfonyBundleFrameworkBundleTemplatingGlobalVariables;
use SymfonyComponentTemplatingTemplateNameParserInterface;
use SymfonyComponentConfigFileLocatorInterface;
use SolilokiamRequestListenerBundleManagerDeviceManager;
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 SolilokiamFrontBundleController;
use SymfonyBundleFrameworkBundleControllerController;
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/ZenstruckMobileBundle
https://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 flexible
2.Imágenes y media flexibles
Los 3 pilares del Responsive Design
1.Layout basado en un grid flexible
2.Imágenes y media flexibles
3.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 MediaTypes (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:
width
height
device-width
device-height
orientation
aspect ratio
color (bit number)
color-index
monochrome(bits x pixel)
resolution (dpi)
scan(tv progressive o scan)
grid
Media Queries
No solamente podemos filtrar por height o width:
width
height
device-width
device-height
orientation
aspect ratio
color (bit number)
color-index
monochrome(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 tipografias
Modificar 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-design
http://www.youtube.com/watch?v=pDUH1Pjl5Sk
http://www.abookapart.com/products/responsive-web-design
http://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 string
e(@string); // escape string content
%(@string, values...); // formats a string
ceil(@number); // rounds up to an integer
floor(@number); // rounds down to an integer
percentage(@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
Gracias
https://joind.in/8841

Mais conteúdo relacionado

Destaque

Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13Stephan Hochdörfer
 
Leading open source development team on large scale cloud based systems
Leading open source development team on large scale cloud based systemsLeading open source development team on large scale cloud based systems
Leading open source development team on large scale cloud based systemsJanis Janovskis
 
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Kacper Gunia
 
Enough with the JavaScript already!
Enough with the JavaScript already!Enough with the JavaScript already!
Enough with the JavaScript already!Nicholas Zakas
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
Presentacion Iniciación al Responsive Web Design
Presentacion Iniciación al Responsive Web DesignPresentacion Iniciación al Responsive Web Design
Presentacion Iniciación al Responsive Web DesignGeekia
 
The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...
The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...
The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...HighSpark | Visual Storytelling Agency
 

Destaque (9)

PHP's FIG and PSRs
PHP's FIG and PSRsPHP's FIG and PSRs
PHP's FIG and PSRs
 
Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13Phing for power users - dpc_uncon13
Phing for power users - dpc_uncon13
 
Leading open source development team on large scale cloud based systems
Leading open source development team on large scale cloud based systemsLeading open source development team on large scale cloud based systems
Leading open source development team on large scale cloud based systems
 
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
 
Enough with the JavaScript already!
Enough with the JavaScript already!Enough with the JavaScript already!
Enough with the JavaScript already!
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Behat 3.0 meetup (March)
Behat 3.0 meetup (March)Behat 3.0 meetup (March)
Behat 3.0 meetup (March)
 
Presentacion Iniciación al Responsive Web Design
Presentacion Iniciación al Responsive Web DesignPresentacion Iniciación al Responsive Web Design
Presentacion Iniciación al Responsive Web Design
 
The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...
The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...
The Presenter Manifesto : 8 Distinctions of a World Class Presenter by @eric_...
 

Semelhante a Frontal avanzado y assetic

Symfony2 Introducción
Symfony2 IntroducciónSymfony2 Introducción
Symfony2 Introducciónstrate
 
Symfony-Community: Introducción a Symfony Framework
Symfony-Community: Introducción a Symfony FrameworkSymfony-Community: Introducción a Symfony Framework
Symfony-Community: Introducción a Symfony Frameworkexcedesoft
 
Timerepublik
TimerepublikTimerepublik
Timerepublikbetabeers
 
Adentrándonos al Framework Symfony
Adentrándonos al  Framework SymfonyAdentrándonos al  Framework Symfony
Adentrándonos al Framework SymfonyRodrigo Miranda
 
Webinar Monitorización Proactiva con HPE AppPulse Active
Webinar Monitorización Proactiva con HPE AppPulse ActiveWebinar Monitorización Proactiva con HPE AppPulse Active
Webinar Monitorización Proactiva con HPE AppPulse ActiveGlobe Testing
 
DeSymfony 2017 - Symfony en OpenSky
DeSymfony 2017 - Symfony en OpenSkyDeSymfony 2017 - Symfony en OpenSky
DeSymfony 2017 - Symfony en OpenSkyPablo Godel
 
Desarrollo de Aplicaciones Web con Symfony 5/10/2011
Desarrollo de Aplicaciones Web con Symfony 5/10/2011Desarrollo de Aplicaciones Web con Symfony 5/10/2011
Desarrollo de Aplicaciones Web con Symfony 5/10/2011gorolabs
 
Herramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamenteHerramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamenteCarlos Toxtli
 
2015 presentation corporate_alfa9_cast
2015 presentation corporate_alfa9_cast2015 presentation corporate_alfa9_cast
2015 presentation corporate_alfa9_castiñaki bermejo
 
Slides Master Programación de Alto Rendimiento 2015
Slides Master Programación de Alto Rendimiento 2015Slides Master Programación de Alto Rendimiento 2015
Slides Master Programación de Alto Rendimiento 2015Sergi González Pérez
 
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...Pablo Godel
 
Liferay Symposium 2014 - Business case: RACE
Liferay Symposium 2014 - Business case: RACE Liferay Symposium 2014 - Business case: RACE
Liferay Symposium 2014 - Business case: RACE Miguel Ángel Júlvez
 
Aplicaciones Web con Spring Boot
Aplicaciones Web con Spring BootAplicaciones Web con Spring Boot
Aplicaciones Web con Spring BootCarlos E. Salazar
 
Proceso de Migración Joomla 4 - JoomlaDay ES 2023
Proceso de Migración Joomla 4 - JoomlaDay ES 2023Proceso de Migración Joomla 4 - JoomlaDay ES 2023
Proceso de Migración Joomla 4 - JoomlaDay ES 2023SergioIglesiasNET
 
Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...
Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...
Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...joomlaes
 

Semelhante a Frontal avanzado y assetic (20)

Symfony2 Introducción
Symfony2 IntroducciónSymfony2 Introducción
Symfony2 Introducción
 
Symfony-Community: Introducción a Symfony Framework
Symfony-Community: Introducción a Symfony FrameworkSymfony-Community: Introducción a Symfony Framework
Symfony-Community: Introducción a Symfony Framework
 
Timerepublik
TimerepublikTimerepublik
Timerepublik
 
Backbeam
BackbeamBackbeam
Backbeam
 
Adentrándonos al Framework Symfony
Adentrándonos al  Framework SymfonyAdentrándonos al  Framework Symfony
Adentrándonos al Framework Symfony
 
Webinar Monitorización Proactiva con HPE AppPulse Active
Webinar Monitorización Proactiva con HPE AppPulse ActiveWebinar Monitorización Proactiva con HPE AppPulse Active
Webinar Monitorización Proactiva con HPE AppPulse Active
 
DeSymfony 2017 - Symfony en OpenSky
DeSymfony 2017 - Symfony en OpenSkyDeSymfony 2017 - Symfony en OpenSky
DeSymfony 2017 - Symfony en OpenSky
 
Desarrollo de Aplicaciones Web con Symfony 5/10/2011
Desarrollo de Aplicaciones Web con Symfony 5/10/2011Desarrollo de Aplicaciones Web con Symfony 5/10/2011
Desarrollo de Aplicaciones Web con Symfony 5/10/2011
 
Html5
Html5Html5
Html5
 
Herramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamenteHerramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamente
 
2015 presentation corporate_alfa9_cast
2015 presentation corporate_alfa9_cast2015 presentation corporate_alfa9_cast
2015 presentation corporate_alfa9_cast
 
Symfony Parte 3
Symfony Parte 3Symfony Parte 3
Symfony Parte 3
 
Slides Master Programación de Alto Rendimiento 2015
Slides Master Programación de Alto Rendimiento 2015Slides Master Programación de Alto Rendimiento 2015
Slides Master Programación de Alto Rendimiento 2015
 
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...
 
Mobile, ¿todavia pensándolo?
Mobile, ¿todavia pensándolo?Mobile, ¿todavia pensándolo?
Mobile, ¿todavia pensándolo?
 
Liferay Symposium 2014 - Business case: RACE
Liferay Symposium 2014 - Business case: RACE Liferay Symposium 2014 - Business case: RACE
Liferay Symposium 2014 - Business case: RACE
 
Aplicaciones Web con Spring Boot
Aplicaciones Web con Spring BootAplicaciones Web con Spring Boot
Aplicaciones Web con Spring Boot
 
Symfony dagrinchi
Symfony dagrinchiSymfony dagrinchi
Symfony dagrinchi
 
Proceso de Migración Joomla 4 - JoomlaDay ES 2023
Proceso de Migración Joomla 4 - JoomlaDay ES 2023Proceso de Migración Joomla 4 - JoomlaDay ES 2023
Proceso de Migración Joomla 4 - JoomlaDay ES 2023
 
Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...
Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...
Convierte tu Joomla! a estático, haciéndola inhackeable y ultrarrápida - Javi...
 

Último

investigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXIinvestigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXIhmpuellon
 
Buenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptxBuenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptxFederico Castellari
 
Guia Basica para bachillerato de Circuitos Basicos
Guia Basica para bachillerato de Circuitos BasicosGuia Basica para bachillerato de Circuitos Basicos
Guia Basica para bachillerato de Circuitos BasicosJhonJairoRodriguezCe
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21mariacbr99
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxAlan779941
 
How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.FlorenciaCattelani
 
redes informaticas en una oficina administrativa
redes informaticas en una oficina administrativaredes informaticas en una oficina administrativa
redes informaticas en una oficina administrativanicho110
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estossgonzalezp1
 
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxEVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxJorgeParada26
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...JohnRamos830530
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanamcerpam
 

Último (11)

investigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXIinvestigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXI
 
Buenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptxBuenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptx
 
Guia Basica para bachillerato de Circuitos Basicos
Guia Basica para bachillerato de Circuitos BasicosGuia Basica para bachillerato de Circuitos Basicos
Guia Basica para bachillerato de Circuitos Basicos
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
 
How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.
 
redes informaticas en una oficina administrativa
redes informaticas en una oficina administrativaredes informaticas en una oficina administrativa
redes informaticas en una oficina administrativa
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estos
 
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxEVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvana
 

Frontal avanzado y assetic

  • 1.
  • 2.
  • 3. ¿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 miquel@solilokiam.com @solilokiam http://www.github.com/solilokiam
  • 5. ¿Qué es Ofertix? •Vendemos productos y servicios por internet
  • 6. ¿Qué es Ofertix? •Vendemos productos y servicios por internet •A precios interesantes
  • 7. ¿Qué es Ofertix? •Vendemos productos y servicios por internet •A precios interesantes •Tenemos varias lineas de negocio
  • 8. ¿Qué es Ofertix? •Vendemos productos y servicios por internet •A precios interesantes •Tenemos varias lineas de negocio •Ventas Privadas, Ocio, Full Price yTienda Física
  • 9. ¿Qué es Ofertix? •Vendemos productos y servicios por internet •A precios interesantes •Tenemos varias lineas de negocio •Ventas Privadas, Ocio, Full Price yTienda Física •7 años en marcha
  • 10. ¿Qué es Ofertix? •Vendemos productos y servicios por internet •A precios interesantes •Tenemos varias lineas de negocio •Ventas Privadas, Ocio, Full Price yTienda Física •7 años en marcha •Principalmente Symfony 1.2
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 19. ¿Que Problemas Tenemos? NINGUNO. SOMOS LOS MEJORES http://miexesunameme.blogspot.com.es/2013/05/mientras-tanto-en-clase.html
  • 22. Pero... •Nuestra interfaz móvil es mejorable •Queremos añadir full-text search
  • 23. Pero... •Nuestra interfaz móvil es mejorable •Queremos añadir full-text search •Queremos mejorar lineas de negocio
  • 24. Pero... •Nuestra interfaz móvil es mejorable •Queremos añadir full-text search •Queremos mejorar lineas de negocio •Ya toca un lavado de cara
  • 25. 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
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 37. Solución Re-escribir el frontal de todos nuestros sites. http://symfony.com/logo
  • 38. Solución Re-escribir el frontal de todos nuestros sites. Aplicando lo aprendido de nuestros errores http://symfony.com/logo
  • 40. 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 •...
  • 42. Pero hoy toca... Mobile y otros dispositivos
  • 43. ¿Por qué? Fuente Google Analytics 04/06/2013
  • 44. ¿Por qué? Otros 6% Android Browser 11% Safari IOS 16% Safari Mac 4% Firefox Windows 13% IE Explorer 23% Chrome Windows 27% Fuente Google Analytics 04/06/2013
  • 50. •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
  • 51. Como lo hacemos <?php namespace SolilokiamRequestListenerBundleEventListener; use SymfonyComponentHttpKernelHttpKernelInterface; use SymfonyComponentHttpKernelEventGetResponseEvent; use SolilokiamRequestListenerBundleDetectorDeviceDetector; class RequestListener { public function onKernelRequest(GetResponseEvent $event) { $detector = new DeviceDetector(); $request = $event->getRequest(); $user_agent = $request->headers->get('user-agent'); if($detector->isMobile($user_agent)) { $request->setRequestFormat('mobile', 'text/html'); } 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'); } } }
  • 52. <?php namespace SolilokiamRequestListenerBundleDetector; 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
  • 53. parameters: solilokiam_request_listener.example.class: SolilokiamRequestListenerBundleEventListenerRequestListener services: solilokiam_request_listener.example: class: %solilokiam_request_listener.example.class% tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } <?php namespace SolilokiamFrontBundleController; use SymfonyBundleFrameworkBundleControllerController; 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
  • 54.
  • 56. 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: it@ofertix.com http://alba-twist.blogspot.com.es/2011_10_01_archive.html
  • 57. <?php namespace SolilokiamRequestListenerBundleEventListener; use SymfonyComponentHttpKernelHttpKernelInterface; use SymfonyComponentHttpKernelEventGetResponseEvent; use SymfonyComponentHttpKernelHttpKernel; use SolilokiamRequestListenerBundleManagerDeviceRedirectManager;use SolilokiamRequestListenerBundleManagerDeviceManager; 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)
  • 58. Como lo hacemos (pero mejor) <?php namespace SolilokiamRequestListenerBundleManager; use SolilokiamRequestListenerBundleDetectorDeviceDetector; 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); } } }
  • 59. <?php namespace SolilokiamRequestListenerBundleManager; //use SolilokiamRequestListenerBundleManagerDeviceManager;use SymfonyComponentHttpFoundationRedirectResponse; 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(); Como lo hacemos (pero mejor)
  • 60. 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)
  • 61. <?php namespace SolilokiamRequestListenerBundleTwig; use SymfonyBundleTwigBundleTwigEngine as BaseTwigEngine; use SymfonyBundleFrameworkBundleTemplatingGlobalVariables; use SymfonyComponentTemplatingTemplateNameParserInterface; use SymfonyComponentConfigFileLocatorInterface; use SolilokiamRequestListenerBundleManagerDeviceManager; 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)
  • 62. Como lo hacemos (pero mejor) <?php namespace SolilokiamFrontBundleController; use SymfonyBundleFrameworkBundleControllerController; class DefaultController extends Controller { public function indexAction($name) { return $this->render('SolilokiamFrontBundle:Default:index.html.twig', array('name' => $name));} }
  • 64. 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
  • 65. 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/ZenstruckMobileBundle https://github.com/suncat2000/MobileDetectBundle http://www.vayagif.com/169459/claro-que-si-campeon-michael-jackson-estaria-orgulloso-de-ti
  • 66. 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
  • 67. 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*
  • 68. ¿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
  • 69.
  • 70. Los 3 pilares del Responsive Design
  • 71. Los 3 pilares del Responsive Design 1.Layout basado en un grid flexible
  • 72. Los 3 pilares del Responsive Design 1.Layout basado en un grid flexible 2.Imágenes y media flexibles
  • 73. Los 3 pilares del Responsive Design 1.Layout basado en un grid flexible 2.Imágenes y media flexibles 3.Media Queries
  • 74. Layout basado en un grid flexible
  • 75. 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; }
  • 76. 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
  • 77. .blog .main { float: left; padding: 17px; width: 678px; } Un Cálculo de Ejemplo
  • 78. .blog .main { float: left; padding: 17px; width: 678px; } 678 / 970 * 100 = 69,896907216495 Un Cálculo de Ejemplo
  • 79. .blog .main { float: left; padding: 17px; width: 678px; } 678 / 970 * 100 = 69,896907216495 Un Cálculo de Ejemplo 17 / 970 * 100 = 1,752577319588
  • 80. 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%; }
  • 81. ¿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 = ¿?
  • 82. ¿Y qué pasa con la tipografia? El tamaño por defecto de la fuente suele ser 16px
  • 83. ¿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
  • 84. ¿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
  • 85. ¿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%; }
  • 86. ¿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/
  • 87. ¿Y qué pasa con la tipografia? Aplicamos la misma regla de calculo h1 { font-size: 24px; } h1 a { font-size: 11px; }
  • 88. ¿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
  • 89. ¿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
  • 90. ¿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; }
  • 91. Imágenes y media flexibles Varias Opciones: •Resize •Crop •HTML5 picture tag •Clown Car
  • 94. Resize img, embed, object, video { max-width: 100%; } •La solución más compatible •Ancho de Banda Poco Optimo •Renderizado en navegador poco optimo
  • 95. 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
  • 96. 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
  • 97. 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>
  • 98. 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
  • 99. Media Queries Desarrollado a partir de los MediaTypes (CSS 2) @media screen { body { font-size: 100%; } } @media print { body { font-size: 15pt; } }
  • 100. Media Queries @media screen and (min-width: 1024px) { body { font-size: 100%; } } <link rel="stylesheet" href="wide.css" media="screen and (min-width: 1024px)" />
  • 101. Media Queries No solamente podemos filtrar por height o width: width height device-width device-height orientation aspect ratio color (bit number) color-index monochrome(bits x pixel) resolution (dpi) scan(tv progressive o scan) grid
  • 102. Media Queries No solamente podemos filtrar por height o width: width height device-width device-height orientation aspect ratio color (bit number) color-index monochrome(bits x pixel) resolution (dpi) scan(tv progressive o scan) grid @media screen and (min-device-width: 480px) and (orientation: landscape) { ... }
  • 103. Media Queries Arreglar todas las cosas que no se acaban de adaptar con Layout basado en un grid flexible
  • 104. Media Queries Arreglar todas las cosas que no se acaban de adaptar con Layout basado en un grid flexible Cambiar tipografias Modificar layout Mostrar / Ocultar elementos ...
  • 105. 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
  • 109. Preprocesadores CSS •Ahorro de muchas horas de maquetación •Cambios Rápidos •Código Estructurado Assetic los integra perfectamente en nuestros proyectos.
  • 110. Instalar nodeJS + npm $ npm install less Symfony
  • 111. Instalar nodeJS + npm $ npm install less assetic: filters: cssrewrite: ~ less: node: /usr/local/bin/node node_paths: [/usr/local/lib/node_modules] Symfony
  • 112. 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
  • 113. 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
  • 114. 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
  • 116. Variables @azul: #5B83AD; @azul-claro: (@azul + #111); #header { color: @azul-claro; }
  • 117. Variables @azul: #5B83AD; @azul-claro: (@azul + #111); #header { color: @azul-claro; } #header { color: #6c94be; }
  • 118. 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
  • 119. 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;
  • 120. 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";
  • 121. Mixins .bordered { border-top: dotted 1px black; border-bottom: solid 2px black; } #menu a { color: #111; .bordered; }
  • 122. 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; }
  • 123. 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; }
  • 124. 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; }
  • 126. Mixins Multiples Parametros separados por semicolon Less permite sobrecarga en los mixins
  • 127. 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); }
  • 128. 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; }
  • 129. Mixins .margin_mixin(@top; @right; @down; @left) { margin: @arguments; } .margin_mixin(2px; 5px;2px;5px);
  • 130. Mixins .margin_mixin(@top; @right; @down; @left) { margin: @arguments; } .margin_mixin(2px; 5px;2px;5px); margin: 2px 5px 2px 5px;
  • 131. !important .test_mixin (@a: 0) { margin: @a; padding: @a; } .no_importante { .test_mixin(1); } .muy_importante { .test_mixin(2) !important; }
  • 132. !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; }
  • 133. Nested Rules #header { color: black; } #header .navigation { font-size: 12px; } #header .logo { width: 300px; } #header .logo:hover { text-decoration: none; }
  • 134. 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 } } }
  • 135. Operations •Afectan a numeros y colores •Tienen que ir entre paréntesis
  • 136. 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)); }
  • 137. 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%; }
  • 140. 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; }
  • 141. 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; }
  • 142. Funciones escape(@string); // URL encodes a string e(@string); // escape string content %(@string, values...); // formats a string ceil(@number); // rounds up to an integer floor(@number); // rounds down to an integer percentage(@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*
  • 143. Pattern Matching .mixin (dark; @color) { color: darken(@color, 10%); } .mixin (light; @color) { color: lighten(@color, 10%); } .mixin (@_; @color) { display: block; }
  • 144. 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); }
  • 145. 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; }
  • 146. Guarded Params .mixin (@a) when (lightness(@a) >= 50%) { background-color: black; } .mixin (@a) when (lightness(@a) < 50%) { background-color: white; } .mixin (@a) { color: @a; }
  • 147. 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) }
  • 148. 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; }
  • 149. Comentarios /* Hola soy un comentario la mar de interesante */ .test_class { color: #008866 }
  • 150. 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 }
  • 151. 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 }
  • 152. 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 }
  • 153. Quiero saber más. http://lesscss.org http://twitter.github.io/bootstrap/ http://lesshat.com/
  • 154. Quiero saber más. http://lesscss.org http://twitter.github.io/bootstrap/ http://lesshat.com/ ¿Qué pasa con SASS?
  • 155. 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
  • 156. 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/
  • 157. Resumiendo •Adaptad vuestra aplicación a varios devices •Analizad vuestras necesidades •Aplicad la técnica que mejor os vaya •Utilizad preprocesadores de CSS