3D & Animation Effects Using CSS3 & jQuery

770 views
674 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
770
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
36
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

3D & Animation Effects Using CSS3 & jQuery

  1. 1. 3D & animation effects implementing animation & 3D using CSS3 & jQuery presented by Vu Tran Lam Saturday, March 9, 13
  2. 2. the web is less than 9000 days old http://wwwflickr.com/photos/psd/3149878971 Saturday, March 9, 13
  3. 3. 1/3 2012 estimates put the population at about 7 billion inhabitants... Internet of people on planet using Saturday, March 9, 13
  4. 4. 1/3 people has a smartphone of Saturday, March 9, 13
  5. 5. the smartphone era begins... Saturday, March 9, 13
  6. 6. brings touch, gestures iPhone 3G web touch and the real web... iPhone 2007 2008 Saturday, March 9, 13
  7. 7. 20082007 2009 3GiPhone iPhone 3GS native apps and android apps the rise of Android... Saturday, March 9, 13
  8. 8. 2008 2009 3G 2010 3GS 2011 4 blackberry kindle nook devices go mainstream iPhone 5... with great expectations... samsung motorola htc LG Saturday, March 9, 13
  9. 9. web evaluation... Saturday, March 9, 13
  10. 10. Saturday, March 9, 13
  11. 11. Saturday, March 9, 13
  12. 12. Saturday, March 9, 13
  13. 13. yesterday “go to the computer” to use the web/Internet Saturday, March 9, 13
  14. 14. yesterday “go to the computer” to use the web/Internet today “use the mobile” to use the web/Internet Saturday, March 9, 13
  15. 15. 14 small + medium + large Saturday, March 9, 13
  16. 16. 15 one standard for every devices Saturday, March 9, 13
  17. 17. Saturday, March 9, 13
  18. 18. http://www.flickr.com/photos/aubergene/970367879 ...view flash & video on iDevice? Saturday, March 9, 13
  19. 19. http://www.flickr.com/photos/aubergene/970367879 no flash or video but need to find a key... Saturday, March 9, 13
  20. 20. ...in the old days Saturday, March 9, 13
  21. 21. function  MM_timelinePlay(tmLnName,  myID)  {  //v1.2    //Copyright  1998,  1999,  2000,  2001,  2002,  2003,  2004  Macromedia,  Inc.  All  rights  reserved.    var  i,j,tmLn,props,keyFrm,sprite,numKeyFr,firstKeyFr,propNum,theObj,firstTime=false;    if  (document.MM_Time  ==  null)  MM_initTimelines();  //if  *very*  1st  time    tmLn  =  document.MM_Time[tmLnName];    if  (myID  ==  null)  {  myID  =  ++tmLn.ID;  firstTime=true;}//if  new  call,  incr  ID    if  (myID  ==  tmLn.ID)  {  //if  Im  newest        setTimeout('MM_timelinePlay("'+tmLnName+'",'+myID+')',tmLn.delay);        fNew  =  ++tmLn.curFrame;        for  (i=0;  i<tmLn.length;  i++)  {            sprite  =  tmLn[i];            if  (sprite.charAt(0)  ==  's')  {                if  (sprite.obj)  {                    numKeyFr  =  sprite.keyFrames.length;  firstKeyFr  =  sprite.keyFrames[0];                    if  (fNew  >=  firstKeyFr  &&  fNew  <=  sprite.keyFrames[numKeyFr-­‐1])  {//in  range                        keyFrm=1;                        for  (j=0;  j<sprite.values.length;  j++)  {                            props  =  sprite.values[j];                              if  (numKeyFr  !=  props.length)  {                                if  (props.prop2  ==  null)  sprite.obj[props.prop]  =  props[fNew-­‐firstKeyFr];                                else                sprite.obj[props.prop2][props.prop]  =  props[fNew-­‐firstKeyFr];                            }  else  {                                while  (keyFrm<numKeyFr  &&  fNew>=sprite.keyFrames[keyFrm])  keyFrm++;                                if  (firstTime  ||  fNew==sprite.keyFrames[keyFrm-­‐1])  {                                    if  (props.prop2  ==  null)  sprite.obj[props.prop]  =  props[keyFrm-­‐1];                                    else                sprite.obj[props.prop2][props.prop]  =  props[keyFrm-­‐1];                }  }  }  }  }            }  else  if  (sprite.charAt(0)=='b'  &&  fNew  ==  sprite.frame)  eval(sprite.value);            if  (fNew  >  tmLn.lastFrame)  tmLn.ID  =  0;    }  } } ...in the old days Saturday, March 9, 13
  22. 22. function  MM_timelinePlay(tmLnName,  myID)  {  //v1.2    //Copyright  1998,  1999,  2000,  2001,  2002,  2003,  2004  Macromedia,  Inc.  All  rights  reserved.    var  i,j,tmLn,props,keyFrm,sprite,numKeyFr,firstKeyFr,propNum,theObj,firstTime=false;    if  (document.MM_Time  ==  null)  MM_initTimelines();  //if  *very*  1st  time    tmLn  =  document.MM_Time[tmLnName];    if  (myID  ==  null)  {  myID  =  ++tmLn.ID;  firstTime=true;}//if  new  call,  incr  ID    if  (myID  ==  tmLn.ID)  {  //if  Im  newest        setTimeout('MM_timelinePlay("'+tmLnName+'",'+myID+')',tmLn.delay);        fNew  =  ++tmLn.curFrame;        for  (i=0;  i<tmLn.length;  i++)  {            sprite  =  tmLn[i];            if  (sprite.charAt(0)  ==  's')  {                if  (sprite.obj)  {                    numKeyFr  =  sprite.keyFrames.length;  firstKeyFr  =  sprite.keyFrames[0];                    if  (fNew  >=  firstKeyFr  &&  fNew  <=  sprite.keyFrames[numKeyFr-­‐1])  {//in  range                        keyFrm=1;                        for  (j=0;  j<sprite.values.length;  j++)  {                            props  =  sprite.values[j];                              if  (numKeyFr  !=  props.length)  {                                if  (props.prop2  ==  null)  sprite.obj[props.prop]  =  props[fNew-­‐firstKeyFr];                                else                sprite.obj[props.prop2][props.prop]  =  props[fNew-­‐firstKeyFr];                            }  else  {                                while  (keyFrm<numKeyFr  &&  fNew>=sprite.keyFrames[keyFrm])  keyFrm++;                                if  (firstTime  ||  fNew==sprite.keyFrames[keyFrm-­‐1])  {                                    if  (props.prop2  ==  null)  sprite.obj[props.prop]  =  props[keyFrm-­‐1];                                    else                sprite.obj[props.prop2][props.prop]  =  props[keyFrm-­‐1];                }  }  }  }  }            }  else  if  (sprite.charAt(0)=='b'  &&  fNew  ==  sprite.frame)  eval(sprite.value);            if  (fNew  >  tmLn.lastFrame)  tmLn.ID  =  0;    }  } } ...in the old days Saturday, March 9, 13
  23. 23. function  MM_timelinePlay(tmLnName,  myID)  {  //v1.2    //Copyright  1998,  1999,  2000,  2001,  2002,  2003,  2004  Macromedia,  Inc.  All  rights  reserved.    var  i,j,tmLn,props,keyFrm,sprite,numKeyFr,firstKeyFr,propNum,theObj,firstTime=false;    if  (document.MM_Time  ==  null)  MM_initTimelines();  //if  *very*  1st  time    tmLn  =  document.MM_Time[tmLnName];    if  (myID  ==  null)  {  myID  =  ++tmLn.ID;  firstTime=true;}//if  new  call,  incr  ID    if  (myID  ==  tmLn.ID)  {  //if  Im  newest        setTimeout('MM_timelinePlay("'+tmLnName+'",'+myID+')',tmLn.delay);        fNew  =  ++tmLn.curFrame;        for  (i=0;  i<tmLn.length;  i++)  {            sprite  =  tmLn[i];            if  (sprite.charAt(0)  ==  's')  {                if  (sprite.obj)  {                    numKeyFr  =  sprite.keyFrames.length;  firstKeyFr  =  sprite.keyFrames[0];                    if  (fNew  >=  firstKeyFr  &&  fNew  <=  sprite.keyFrames[numKeyFr-­‐1])  {//in  range                        keyFrm=1;                        for  (j=0;  j<sprite.values.length;  j++)  {                            props  =  sprite.values[j];                              if  (numKeyFr  !=  props.length)  {                                if  (props.prop2  ==  null)  sprite.obj[props.prop]  =  props[fNew-­‐firstKeyFr];                                else                sprite.obj[props.prop2][props.prop]  =  props[fNew-­‐firstKeyFr];                            }  else  {                                while  (keyFrm<numKeyFr  &&  fNew>=sprite.keyFrames[keyFrm])  keyFrm++;                                if  (firstTime  ||  fNew==sprite.keyFrames[keyFrm-­‐1])  {                                    if  (props.prop2  ==  null)  sprite.obj[props.prop]  =  props[keyFrm-­‐1];                                    else                sprite.obj[props.prop2][props.prop]  =  props[keyFrm-­‐1];                }  }  }  }  }            }  else  if  (sprite.charAt(0)=='b'  &&  fNew  ==  sprite.frame)  eval(sprite.value);            if  (fNew  >  tmLn.lastFrame)  tmLn.ID  =  0;    }  } } Ugh, terrible code ...in the old days Saturday, March 9, 13
  24. 24. you could not design graphic http://www.flickr.com/photos/handwrite/3460075040 IMPOSSIBLE & animation on website... Saturday, March 9, 13
  25. 25. http://www.flickr.com/photos/vauvau/3466024918 animation & 3D effects really bloody difficult... this technique is Saturday, March 9, 13
  26. 26. http://www.flickr.com/photos/clairity/1449248189 ...we can not find a suitable tree in the forest Saturday, March 9, 13
  27. 27. http://www.flickr.com/photos/seatbelt67/502255276 hmm... Saturday, March 9, 13
  28. 28. 25 ways...? Saturday, March 9, 13
  29. 29. 26 ...need a team Saturday, March 9, 13
  30. 30. http://www.flickr.com/photos/farleyj/2768941171 Eureka! HMTL5 & CSS3 Saturday, March 9, 13
  31. 31. welcome to w3c... Saturday, March 9, 13
  32. 32. 29 the next Web Standards Saturday, March 9, 13
  33. 33. Saturday, March 9, 13
  34. 34. semantic layout Web forms 2.0 audio & video 2D & 3D drawing Saturday, March 9, 13
  35. 35. rounded corners gradient fill transition & animation depth content Saturday, March 9, 13
  36. 36. q http://www.flickr.com/photos/sporst/3999795549 ...let's first deal with HTML5 Canvas & Video graphic Saturday, March 9, 13
  37. 37. ...too many HTTP requests provide alternates? unsupported...that's a lot of JavaScript! requests... ...is Flash even supported? does every device support Flash? ...ah, that is Flash! the right version of media formats... Saturday, March 9, 13
  38. 38. HTML5 video suitable for each browser ...screen size? ...available bandwidth? for each browser... media format a couple c.2000... fsdfffSaturday, March 9, 13
  39. 39. Saturday, March 9, 13
  40. 40. Saturday, March 9, 13
  41. 41. Saturday, March 9, 13
  42. 42. HTML5 Canvas Saturday, March 9, 13
  43. 43. using Canvas <html> <head>...</head> <body> <h1>Page  Heading</h1> <p>Lorem  ipsum...</p> <canvas  id="picture1" width="400" height="300"/> <p>Lorem  ipsum...</p>   </body> </html> Page Heading Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. orem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. orem ipsum dolor sit amet, consectetur adipisicing elit, sed do Saturday, March 9, 13
  44. 44. What is the difference between 2 logos? Canvas logo PNG logo Saturday, March 9, 13
  45. 45. ...and demo Saturday, March 9, 13
  46. 46. q http://www.flickr.com/photos/sporst/3999795549 ...let's continue with 3D effect using CSS3 Saturday, March 9, 13
  47. 47. conveying depth with CSS3 Saturday, March 9, 13
  48. 48. transforms -­‐webkit-­‐transform:translateY(200px); Saturday, March 9, 13
  49. 49. transforms -­‐webkit-­‐transform:translateY(200px)  rotate(45deg); Saturday, March 9, 13
  50. 50. building a Box <div></div> <div></div> <div></div> <div></div> <div></div> </div> <div  class=“package”> Saturday, March 9, 13
  51. 51. x5 building a Box Saturday, March 9, 13
  52. 52. building a Box with 3DTransforms z x y Saturday, March 9, 13
  53. 53. z x y .package  >  div:nth-­‐child(1)  { -­‐webkit-­‐transform:translateZ(200px); } building a Box with 3DTransforms Saturday, March 9, 13
  54. 54. building a Box with 3DTransforms           x z   y       .package  >  div:nth-­‐child(1)  { -­‐webkit-­‐transform:translateZ(200px); } Saturday, March 9, 13
  55. 55.                 x z y .package  >  div:nth-­‐child(2)  { -­‐webkit-­‐transform:rotateY(90deg); } building a Box with 3DTransforms Saturday, March 9, 13
  56. 56. x       z y -­‐webkit-­‐transform: rotateY(90deg)  translateZ(200px); .package  >  div:nth-­‐child(2)  { } building a Box with 3DTransforms Saturday, March 9, 13
  57. 57. x       z y -­‐webkit-­‐transform: rotateY(90deg)  translateZ(200px); .package  >  div:nth-­‐child(2)  { } building a Box with 3DTransforms Saturday, March 9, 13
  58. 58. 52 building a Box with 3DTransforms Saturday, March 9, 13
  59. 59. a 3D Box? Saturday, March 9, 13
  60. 60. perspective Saturday, March 9, 13
  61. 61. -webkit-perspective:400px; Saturday, March 9, 13
  62. 62. -webkit-perspective:800px; Saturday, March 9, 13
  63. 63. -webkit-perspective:8000px; Saturday, March 9, 13
  64. 64. adding perspective -­‐webkit-­‐perspective:800px; .package  { } Saturday, March 9, 13
  65. 65. 3D Box with perspective Saturday, March 9, 13
  66. 66. ...and demo Saturday, March 9, 13
  67. 67. q http://www.flickr.com/photos/sporst/3999795549 ...let's continue with transition effect using CSS3 Saturday, March 9, 13
  68. 68. rotating a Box <div  class=“package”>  <div></div>  <div></div>  <div></div>  <div></div>  <div></div> </div> Saturday, March 9, 13
  69. 69. <div></div> <div></div> <div></div> <div></div> <div></div>  </div> </div> <div  class=“package_container”>  <div  class=“package”> rotating a Box Saturday, March 9, 13
  70. 70. .package  { -­‐webkit-­‐perspective:800px; } rotating a Box Saturday, March 9, 13
  71. 71. .package  { } .package_container  { -­‐webkit-­‐perspective:800px; } rotating a Box Saturday, March 9, 13
  72. 72. .package  { -­‐webkit-­‐transform-­‐style:preserve-­‐3d; } .package_container  { -­‐webkit-­‐perspective:800px; } rotating a Box Saturday, March 9, 13
  73. 73. .package  { } rotating a Box Saturday, March 9, 13
  74. 74. .package  { } .package.right_side  { -­‐webkit-­‐transform:rotateY(-­‐90deg); } class=“package  right_side” rotating a Box Saturday, March 9, 13
  75. 75. rotating a Box .package  {      -­‐webkit-­‐transition:-­‐webkit-­‐transform  1s; } .package.right_side  { -­‐webkit-­‐transform:rotateY(-­‐90deg); } class=“package  right_side” Saturday, March 9, 13
  76. 76. rotating a Box .package  {      -­‐webkit-­‐transition:-­‐webkit-­‐transform  1s; } .package.right_side  { -­‐webkit-­‐transform:rotateX(-­‐90deg); } class=“package” Saturday, March 9, 13
  77. 77. rotating a Box .package  {      -­‐webkit-­‐transition:-­‐webkit-­‐transform  1s; } .package.inside  { -­‐webkit-­‐transform:rotateX(-­‐90deg); } class=“package  inside” Saturday, March 9, 13
  78. 78. applying a Transition without javascript Saturday, March 9, 13
  79. 79. .sticker  { background-­‐position:-­‐30px; border-­‐radius:5px; } .sticker:hover  { background-­‐position:0; border-­‐bottom-­‐left-­‐radius:50%  20px; box-­‐shadow:-­‐5px  10px  15px  rgba(0,0,0,0.25); } applying a Transition without javascript Saturday, March 9, 13
  80. 80. transition on hover background-­‐position, border-­‐bottom-­‐left-­‐radius, box-­‐shadow; -­‐webkit-­‐transition-­‐duration:1s; } .sticker:hover  { background-­‐position:0; border-­‐bottom-­‐left-­‐radius:50%  20px; } .sticker  { background-­‐position:-­‐30px; border-­‐radius:5px; -­‐webkit-­‐transition-­‐property: Saturday, March 9, 13
  81. 81. stamp keyframe animation 0% middle flat small 100% top right rotated small 25% flipped 50% flipped big Saturday, March 9, 13
  82. 82. @-­‐webkit-­‐keyframes stamp keyframe animation Saturday, March 9, 13
  83. 83. @-­‐webkit-­‐keyframes  stamp-­‐it  { } Animation  name stamp keyframe animation Saturday, March 9, 13
  84. 84. 25%  { } 50%  { } 100%  { } } @-­‐webkit-­‐keyframes  stamp-­‐it  { stamp keyframe animation Saturday, March 9, 13
  85. 85. 25%  { } 50%  { } 100%  { top:30px; right:30px; } }   @-­‐webkit-­‐keyframes  stamp-­‐it  { stamp keyframe animation Saturday, March 9, 13
  86. 86. 25%  { -­‐webkit-­‐transform:translateZ(200px)  rotateY(-­‐45deg)  rotateX(-­‐30deg); } 50%  { -­‐webkit-­‐transform:translateZ(300px)  rotateY(-­‐45deg)  rotateX(-­‐30deg); } 100%  { top:30px; right:30px; -­‐webkit-­‐transform:rotate(-­‐5deg); @-­‐webkit-­‐keyframes  stamp-­‐it  { stamp keyframe animation } Saturday, March 9, 13
  87. 87. 25%  { -­‐webkit-­‐transform:translateZ(200px)  rotateY(-­‐45deg)  rotateX(-­‐30deg); } 50%  { -­‐webkit-­‐transform:translateZ(300px)  rotateY(-­‐45deg)  rotateX(-­‐30deg) scale(2); } 100%  { top:30px; right:30px; -­‐webkit-­‐transform:rotate(-­‐5deg); @-­‐webkit-­‐keyframes  stamp-­‐it  { stamp keyframe animation } Saturday, March 9, 13
  88. 88. @-­‐webkit-­‐keyframes  stamp-­‐it  {...} </style> <style> stamp keyframe animation Saturday, March 9, 13
  89. 89. @-­‐webkit-­‐keyframes  stamp-­‐it  {...} </style> <style> stamp keyframe animation <script> function  onClickHandler(event)  { var  stampElement  =  /*  get  the  element  */; var  stampElement.style.webkitAnimation  =  “stamp-­‐it  0.5s”; } </script> Saturday, March 9, 13
  90. 90. animation fill mode 0%  {  background-­‐color:  orange;  } 50%  {  background-­‐color:  white;  } 100%  {  background-­‐color:  orange;  } } div.square  { width:100px; height:100px; -­‐webkit-­‐animation:pulse  2s; -­‐webkit-­‐animation-­‐delay:1s; } @-­‐webkit-­‐keyframes  pulse  { Saturday, March 9, 13
  91. 91. 2 second pulse 1 second delay animation fill mode 0%  {  background-­‐color:  orange;  } 50%  {  background-­‐color:  white;  } 100%  {  background-­‐color:  orange;  } } div.square  { width:100px; height:100px; -­‐webkit-­‐animation:pulse  2s; -­‐webkit-­‐animation-­‐delay:1s; } @-­‐webkit-­‐keyframes  pulse  { Saturday, March 9, 13
  92. 92. 2 second pulse 1 second delay animation fill mode 0%  {  background-­‐color:  orange;  } 50%  {  background-­‐color:  white;  } 100%  {  background-­‐color:  orange;  } } div.square  { width:100px; height:100px; -­‐webkit-­‐animation:pulse  2s; -­‐webkit-­‐animation-­‐delay:1s; -­‐webkit-­‐animation-­‐fill-­‐mode:backwards; } @-­‐webkit-­‐keyframes  pulse  { Saturday, March 9, 13
  93. 93. @-­‐webkit-­‐keyframes  stamp-­‐it  {...} <script> function      onClickHandler(event)      { var  stampElement  =  /*  code  to  get  the  element  */; var  stampElement.style.webkitAnimation  =  “stamp-­‐it  0.5s  forwards”; } </script <style> animation fill mode </style> Saturday, March 9, 13
  94. 94. progress indicator 0%  { -­‐webkit-­‐transform:rotate(0); 100%  { -­‐webkit-­‐transform:rotate(360deg); } @-­‐webkit-­‐keyframes  outer  { Saturday, March 9, 13
  95. 95. progress indicator 0%  { -­‐webkit-­‐transform:rotate(5); 100%  { -­‐webkit-­‐transform:rotate(365deg); } @-­‐webkit-­‐keyframes  inner  { Saturday, March 9, 13
  96. 96. .outer_paw { -­‐webkit-­‐animation:outer  5s  infinite; } .inner_paw { -­‐webkit-­‐animation:inner  5s  0.4s  infinite; } progress indicator Saturday, March 9, 13
  97. 97. .outer_paw { -­‐webkit-­‐animation:outer  5s  infinite; -­‐webkit-­‐animation-­‐timing-­‐function:steps(10); } .inner_paw { -­‐webkit-­‐animation:inner  5s  0.4s  infinite; -­‐webkit-­‐animation-­‐timing-­‐function:steps(10); } SteppedTiming function Saturday, March 9, 13
  98. 98. applying a transition .box { background-­‐color:white; -­‐webkit-­‐transition:opacity  1s; } .box:hover { background-­‐color:orange; } Saturday, March 9, 13
  99. 99. .box { background-­‐color:white; -­‐webkit-­‐animation:fade  1s; } @-­‐webkit-­‐keyframes  fade { from  {  background-­‐color:white;  } from  {  background-­‐color:orange;  } } applying a keyframe animation Saturday, March 9, 13
  100. 100. keyframe animation with multiple keyframes .box { background-­‐color:white; -­‐webkit-­‐animation:fade  1s; } @-­‐webkit-­‐keyframes  fade { from  {  background-­‐color:white;  } 50%  {  background-­‐color:  cyan  } to  {  background-­‐color:orange;  } } Saturday, March 9, 13
  101. 101. repeating keyframe animation .box { background-­‐color:white; -­‐webkit-­‐animation:fade  1s; -­‐webkit-­‐animation-­‐iteration-­‐count:infinite; } @-­‐webkit-­‐keyframes  fade { from  {  background-­‐color:white;  } 50%  {  background-­‐color:  cyan  } to  {  background-­‐color:orange;  } } Saturday, March 9, 13
  102. 102. ...and demo Saturday, March 9, 13
  103. 103. http://www.flickr.com/photos/aturkus/4040454167 Saturday, March 9, 13
  104. 104. ... and in the real life Saturday, March 9, 13
  105. 105. web showcases Saturday, March 9, 13
  106. 106. ...and demo Saturday, March 9, 13
  107. 107. Saturday, March 9, 13
  108. 108. responsive websites suitable for any device Saturday, March 9, 13
  109. 109. ...and demo Saturday, March 9, 13
  110. 110. jQuery frameworks Saturday, March 9, 13
  111. 111. jQueryUI frameworks Saturday, March 9, 13
  112. 112. Saturday, March 9, 13
  113. 113. Jaws HTML5 Javascript Game Lib web game frameworks Saturday, March 9, 13
  114. 114. Saturday, March 9, 13
  115. 115. ...and demo Saturday, March 9, 13
  116. 116. go to the heaven... Saturday, March 9, 13
  117. 117. mobile development Saturday, March 9, 13
  118. 118. references Apple Safari Developer https://developer.apple.com/devcenter/ safari/index.action Smashing Magazine Graphic, CSS and Web design http://www.smashingmagazine.com Ben Frain Everything needed to code websites in HTML5 and CSS3 that are responsive to every device Tuts+ Great web design tutorials and articles http://webdesign.tutsplus.com Saturday, March 9, 13
  119. 119. many thanks to thank you lamvt@fpt.com.vn please say tutsplus https://developer.apple.com developer https://tutsplus.com xin chào http://www.smashingmagazine.com smashingmagazine Saturday, March 9, 13

×