29 בספט׳ 2012

CSS - Selectors - 1, Universal & Descendant Selectors

אז איך כותבים קוד css?


הדבר הראשון שחשוב להבין הוא שקוד css, כמו html, נכתוב באמצעות עורך טקסט (אפשר גם עם  Notepad).
במידה ואנחנו כותבים קבצי css חיצוניים, נכתוב את הקוד ללא תגיות html אלא בתחביר css נקי וניתן לקובץ סיומת css.
עיצובי css מורכבים משני חלקים:
  1. Selector - מעין קוד המייצג קבוצה של תגיות בדף (אחת או יותר) עליהן חל העיצוב. ישנו למשל selector שבוחר את כל הכותרות מסוג h1 בדף, selector שבוחר את כל הקישורים (תגיות a) בדף וכו'.
  2. Properties - קבוצה של מאפיינים וערכים, כלומר העיצוב עצמו. שינוי צבע רקע, סוג גופן, גודל, מסגרת ועוד הרבה. 
Selectorים ומאפיינים באים ביחד, כאשר לכל selector אנחנו מגדירים קבוצה של מאפיינים. 
הנה התחביר:
selector { 
    property: value;
    another-property: value;
    /* More Properties.. */ 
} 
במידה ויש מעט מאפיינים אפשר גם לרשום:
selector {property: value; another-property: another-value;}

Selectors

אמרנו שיש לנו מספר דרכים להחיל עיצוב css:

  • inline  - בתוך התגית
  • internal - בתוך הקובץ
  • external - בקובץ חיצוני
כתיבת קוד inline די פשוטה - מוסיפים לתגית אותה רוצים לעצב מאפיין style ובתוכו רושמים את עיצוב ה-css.
כאשר אנחנו רוצים להפריד את העיצוב מקוד html, אנחנו צריכים למצוא שיטה לבחור אלמנטים לעיצוב.

היתרון בבחירת אלמנטים, להבדיל מכתיבת css במאפיין style, הוא היכולת להגדיר עיצוב זהה למספר רב של אלמנטים.

ניקח למשל את הקוד הבא:
table {
 background-color: blue;
}
בדוגמה הזו אנחנו משתמשים ב- selector הכי פשוט שיש - type selector - אנחנו בוחרים את כל הטבלאות בדף וצובעים אותן בצבע רקע כחול.
שימו לב למבנה - selector ובסוגריים מסולסלים מאפיינים וערכים.

את הקוד בדוגמה נוכל לשלב בקובץ html בצורה כזו:
<!DOCTYPE html>
<html>
    <head>
        <title>CSS</title>
        <style type="text/css">
            table {
                background-color: blue;
            }

        </style>    
    </head>
    <body>
        <!-- This table will have blue background -->
        <table>
            <tr>
                <td>I</td>
                <td>have</td>
                <td>blue</td>
                <td>background</td>
            </tr>
        </table>        
    </body>
</html> 
נוכל גם לכתוב את הקוד בקובץ css חיצוני (נקרא לו למשל app.css) ולשלבו בעמוד שלנו באמצעות התגית link:
<link rel="stylesheet" href="app.css"/>
קובץ css יכיל אך ורק קוד css, הנה למשל הקובץ app.css:
/* Main Site Stylesheet */
body {
 font-size: 15px;
 font-family: Arial, serif;
}

table {
 background-color: black;
 color: red;
}

a {
 font-weight: bold;
}

נוכל תמיד להגדיר למספר סלקטורים את אותו עיצוב על ידי שימוש בפסיקים:
table, p {
    background-color: yellow;
}
כאן למשל, הגדרנו לכל הטבלאות (table) ולכל הפסקאות (p) צבע רקע צהוב

אז איזה סלקטורים יש לנו?

חשוב תמיד לדעת ש-css מספק לנו מספר סלקטורים חזקים מאוד שמאפשרים לנו לבחור כמעט כל אלמנט בדף מבלי לשנות את קוד ה-html.
מפתחים רבים מכירים מספר קטן של סלקטורים ומשנים את קוד ה-html כדי שיתאים לגיליונות העיצוב שכתבו.
נסקור כאן את כל סוגי הסלקטורים ב- css2.

 Universal Selector

הסלקטור הכללי מאפשר לנו לפנות לכל התגיות בדף, כלומר להחיל עיצוב על כל האלמנטים בדף.
* {
    background-color: red;
}
כאן צבענו את כל האלמנטים בדף בצבע רקע אדום.

ישנם שימושים נוספים לסלקטור הכללי, נראה אותם בהמשך.

Descendant Selector

כדי להבין כיצד עובד ה- Descendant Selector (סלקטור צאצאים) אנו צריכים להבין את היחסים המשפחתיים בין תגיות html.
נסתכל על הטבלה הבאה:
<table>
    <tr>
        <td>
            <a href="http://my_site.co.il">Click Me!</a>
        </td>
        <td>
            <a href="http://my_site.co.il">Click Me!</a>
        </td>
    </tr>
    <tr>
        <td>
            <a href="http://my_site.co.il">Click Me!</a>
        </td>
        <td>
            <a href="http://my_site.co.il">Click Me!</a>
        </td>
    </tr>
</table>
ב-css ישנם שלושה סוגי יחסים:

  • אב ובן
  • אחים
  • אב-קדמון וצאצא 

בטבלה למעלה אנחנו רואים יחסי אב - ובן בין התגית table לבין התגית tr, כלומר, tr הוא הבן של table ו table הוא האב של tr.

כל תגיות ה-tr נחשבות אחיות, מכיוון שאף אחת לא מוכלת בתוך השנייה ולכולן אותו אב. באותה מידה כל תגיות ה-td הנמצאות באותה שורה גם כן נחשבות אחיות.

התגית a נחשבת צאצאית של table, אך שימו לב, היא נחשבת גם צאצאית ל-td (גם tr נחשבת לצאצאית של table, כמובן). רמת הבן והלאה נחשבת לצאצא.
מצד שני, התגית table נחשבת לאב-קדמון של התגית a כמו גם התגית td.

עכשיו כשהבנו מהם היחסים בין תגיות html, קל לנו להבין כיצד עובד ה Descendant Selector - הוא פשוט בוחר צאצאים, למשל:
table a {
    background-color: green;
}

כאן אנחנו בוחרים את כל הלינקים שנמצאים בתוך טבלה, איפשהו בתוך איזושהי טבלה, או במילים אחרות, את כל הלינקים שהם צאצאים של table.
כל מה שאנחנו צריכים להוסיף כדי להשתמש בסלקטור הוא רווח. נוסיף רווח בין שני סלקטורים אחרים כדי ליצור סלקטור צאצאים.
הנה הקוד המלא:
<!DOCTYPE html>
<html>
    <head>
        <title>Anscestor Selector</title>
        <style type="text/css">
            table a  {
                background-color: green;
            }
        </style>
    </head>
    <body>
        <table>
            <tr>
                <td>
                    <!-- This a tag will have green background -->
                    <a href="http://my_site.co.il">Click Me!</a>
                </td>
                <td>
                    <!-- This one also -->
                    <a href="http://my_site.co.il">Click Me!</a>
                </td>
            </tr>
            <tr>
                <td>
                    <!-- This one also -->
                    <a href="http://my_site.co.il">Click Me!</a>
                </td>
                <td>
                    <!-- This one also -->
                    <a href="http://my_site.co.il">Click Me!</a>
                </td>
            </tr>
        </table>
    </body>
</html>
שימו לב שבכל שלב נוכל לשלב מספר סלקטורים עם פסיקים:
table a, p, div p span {
    background-color: green;
}

  • table a - כל הלינקים שהם צאצאים של table.
  • p - כל הפיסקאות.
  • div p span - כל ה- spans שהם צאצאים של p שהם צאצאים של div. 
זוכרים את ה Universal Selector? גם כאן נוכל להשתמש בו, שימו לב לדוגמה הבאה:
div * a {
    color: red;
}
הסלקטור הזה, למשל, יצבע את הטקסט בכל הלינקים שהם לפחות נכדים (צאצאים מדור שני) של התגית div.
במילים אחרות אפשר להגיד ש-a חייב להיות צאצא של איזושהי תגית (כוכבית), והיא חייבת להיות צאצאית ל div - כלומר חייבת להיות איזושהי תגית בין a ל div בהיררכיה.

בפוסט הבא נראה סלקטורים שימושיים נוספים..

לחסרי הסבלנות:

http://www.w3.org/TR/CSS2/selector.html 

28 בספט׳ 2012

מבוא - CSS - חלק 2

עוד רגע לפני שממשיכים ליצירת עמודי css אמיתיים, חשוב שנבין כיצד css עובד.

CSS - Cascading Style Sheets, למה Cascading?

הדבר הראשון שצריך להבין הוא המונח Cascading - מדורגים. 
כשרק התחילו להגות רעיונות לגבי css, היו שפות נוספות שהתחרו על התקן לעיצוב דפי HTML, אבל יכולת יצירת העיצוב המדורג נתן ל-css יתרון משמעותי על פני האחרות. 

כדי להבין מדוע גליונות css נקראים "מדורגים" אנחנו צריכים קודם כל להבין איפה אפשר לכתוב קוד css.
ישנן שלוש אפשרויות: 

Inline - בתוך השורה

הדרך הכי פשוטה לכתיבת קוד css היא באמצעות המאפיין style. 
כמעט לכל התגיות ב body יש את המאפיין style:

<p style="font-size: 1.2em; font-weight: bolder">
 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
 tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
 quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
 consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
 cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
 proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
בדוגמה למעלה אנחנו מדגישים את תוכן התגית p ומשנים את גודל הגופן.
שימו לב שהעיצוב נכתב ברמת התגית, כלומר, ממש בתוך התגית עצמה. כל מה שמופיע כערך של style יהיה עיצוב css.

Internal - בתוך הדף

דרך נוספת, יעילה קצת יותר, תהיה כתיבת הגדרות css ברמת העמוד, כדי לעשות זאת, נוסיף את התגית style ובתוכה נרשום קוד css:
<!DOCTYPE html>
<html>
 <head>
  <title>CSS - Cascading Style Sheets</title>

  <style type="text/css">
  /*
   CSS Styling Goes Here
  */
  </style>
  
 </head>
 <body>
  <!-- HTML BODY CONTENT -->
 </body>
</html>

כפי שאתם רואים, את התגית style נוסיף תחת ה-header והקוד שבתוכה יחול על התגיות באותו הדף. 

ישנה אפשרות נוספת לשימוש ב- Internal css - על ידי ייבוא קוד css מקובץ חיצוני באמצעות הפקודה import@. 
נסתכל על מבנה התיקיות הבא:

אם למשל נרצה לייבא את קוד css מ- internal.css ל- index.html: נרשום בקובץ index.html:
<!DOCTYPE html>
<html>
 <head>
  <title>Internal CSS</title>
  <style type="text/css">

   @import url('style/internal.css');

   /* Rest of CSS Styles */
   
  </style>
 </head>
 <body>
 <!-- HTML BODY CONTENT -->
 </body>
</html>

עכשיו, הקוד המופיע ב internal.css יועבר ל index.html - ויתנהג כ- css פנימי לכל דבר. 
import@ מאפשר לנו לייבא פקודות css בהתאם ללקוח, או לתוכנה שקוראת את גיליונות העיצוב. 
למשל: 
<style type="text/css">
    @import url('style/mobiles.css') handheld;
    @import url('style/printers.css') printer;
</style>

בדוגמה הזו במידה ונגלוש אל הדף באמצעות מכשיר סלולארי, ייטען הקובץ mobiles.css (כרגע הייבוא עובד רק עבור מכשירים סלולארים מודרנים ולא נתמך על ידי כל הפלטפורמות, אבל זה אחלה רעיון)

ובמידה ונשלח את הדף להדפסה, יופיע הדף מעוצב באמצעות הקובץ printers.css .

External - בדף אחר 

קוד internal css, נחמד וטוב כאשר אנחנו רוצים להגדיר סגנונות css עבור אלמנטים בדף אחד, אך css מאפשר לנו ליצור גיליון עיצוב, או קובץ נפרד שיכול לשמש מספר דפים, כלומר קובץ עיצוב אחד שיגדיר את העיצוב לכמה דפים שנרצה. שינוי בקובץ החיצוני יגרור שינוי בכל הדפים המקושרים אליו. 

שאלה מתבקשת היא הגדרת ההבדל בין הפקודה import@ לבין השימוש ב- External css.
ובכן, בגדול אין הרבה הבדל מלבד העובדה ש import@ אינו נתמך בדפדפנים ישנים (יכול לעזור לכם להכניס עיצובים שלא נתמכים בתוכנות ישנות) וגם העובדה ש import@ עדיין נחשב internal (כבר נבין מדוע זה חשוב).

בכל אופן כדי להכניס עיצוב css external לדף, נשתמש בתגית link אותה נוסיף גם כן לתגית ה-header:

<!DOCTYPE html>
<html>
 <head>
  <title>External CSS Example</title>
  <link rel="stylesheet" type="text/css" href="style/external.css"/>
 </head>
 <body>
  <!-- BODY HTML CODE -->
 </body>
</html>
בדוגמה למעלה, קישרנו קובץ חיצוני external.css לדף הנוכחי.

אוקי, אז איך זה קשור ל"מדורג"? 

ובכן, אנחנו צריכים להכיר את שלושת השיטות כדי להבין מה חשיבות הרמות השונות של גילונות עיצוב.
לעיתים קרובות, כאשר אנחנו מעצבים אתר, נוצרים קונפליקטים בעיצובי ה-css.

נתמקד למשל בתגית מסוימת בדף - נניח שהגדרתי לה css inline, כלומר, השתמשתי במאפיין style כדי להגדיר לה עיצוב (כמו שראינו למעלה) - למשל צבע רקע צהוב.
באותו עמוד html, באמצעות שימוש ב css internal, הגדרתי לה צבע רקע ירוק.
ובדף css חיצוני הגדרתי לאותה תגית בדיוק צבע רקע אדום.

ובכן, הגדרתי לאותה תגית שלושה צבעי רקע שונים - אחד inline, אחד internal ואחד external.
מה יהיה צבע הרקע של התגית בסופו של דבר? צהוב.

קונפליקטים כאלו הם לא באג בהגדרת תקן css, הם למעשה רצויים (במובנים מסוימים) כי כמעט תמיד נרצה לעצב תגית אחת בצורה שונה ולדרוס את העיצוב הכללי יותר.

חילקנו את סוגי העיצובים לשלוש רמות מכיוון שלכל אחת מהן יש "חוזק" שונה, כלומר, ככל שההגדרה יותר ספציפית לתגית מסוימת, כך גדלים הסיכויים שלה "לנצח".
מכיוון שאת המאפיין style אנו משייכים לתגית אחת ויחידה, הוא הראשון שיקבע איזה ערך תקבל התגית.
במידה וקיים קונפליקט בין עיצוב internal לבין עיצוב external, כמובן שהעיצוב המוגדר ב-internal "ינצח" מכיוון שזה מוגדר באותו עמוד בו נמצאת התגית בעוד האחר מוגדר בכלל בדף חיצוני אחר (לא כולל import@) ומהווה חוקי עיצוב כלליים יותר לגבי האתר.

נוכל לדרג את שלושת הרמות כך:

  1. Inline - הכי חזק
  2. Internal
  3. External - הכי חלש
 כך ניתן לראות שחוקי העיצוב מדורגים בכמה רמות, כאשר לכל רמה השפעה שונה (בחוזקה) על עיצוב הדף.

אבל רגע...  


עדיין לא פתרנו את כל הבעיות! מה קורה אם יש קונפליקט בין שני עיצובים באותה רמה?
מה אם למשל הגדרנו שני צבעי רקע שונים ברמת ה-internal?

ישנם עוד כלים לבדיקת "חוזק" ההגדרה - עליהם נלמד בהמשך (נוגע ל-selectorים), אבל במידה ובאמת ישנו קונפליקט בין שני כללים בעלי אותו משקל בדיוק - הכלל האחרון מנצח, כלומר, זה שנכתב אחרון או פשוט הכי תחתון בקוד.

אם למשל הגדרנו לתגית צבע רקע אפור ולאחר מכן צבע רקע ירוק - התגית תיצבע בירוק.

לחופרים

נגענו בכמה סוגיות חשובות, אחת מהן היא השימוש ב- import@ מול התגית link - לא דנו בכל ההבדלים. תוכלו למצוא חומר נוסף כאן:
http://webdesign.about.com/od/beginningcss/f/css_import_link.htm
וכאן:
http://www.stevesouders.com/blog/2009/04/09/dont-use-import/ 

CSS - מבוא

בהתחלה בהתחלה, לפני ימי ה-css עמודי אינטרנט עוצבו באמצעות HTML, וזה היה בסדר גמור. 
כל עוד לא עיצבתם את הדף.

אז למה? למה אנחנו צריכים ללמוד עוד טכנולוגיה חדשה בשביל שנוכל לעשות את מה שאפשר היה לעשות ב-HTML? 

באופן מפתיע התשובה מאוד פשוטה - ויש יותר מתשובה אחת:

אפשר לעשות יותר

כשמדובר ב-css, במיוחד בתקן css 2, אפשר לעשות הרבה יותר - כלומר, אפשר לעשות הרבה יותר ממה שהיינו יכולים לעשות רק ב-html. 
רוצים דוגמא פשוטה? שקיפות, אי אפשר להגדיר שקיפות ב-html לבד. ומיקום. ושכבות. וlayoutים, אי אפשר ליצור layoutים שלא באמצעות טבלאות - וראינו כבר כמה נכון וחכם יהיה שימוש בטבלאות.

הדפדפן הפופולארי הראשון, למשל, Mosaic, אפשר למפתחים לכתוב אתרים רק ב-html - מה שגרר המון תלונות מצד עורכי תוכן ששאלו את מפתחי הדפדפן למה אי אפשר לעצב דף אינטרנט כמו שאפשר לעצב דף רגיל ב-Word? זה לא הגיוני?

חשוב לציין שבאותה תקופה עוד לא היה תקן אחיד, והשאיפה לסטנדרט אחיד עוד לא הופנמה אז, שוק הדפדפנים לא היה תחרותי כמו שהוא היום - לא היה מבחר של דפדפנים עם פלחי שוק כמעט זהים (חוץ מ-IE) - לכן דפדפן אחד הכתיב לרוב את התקנים הקיימים כשעוד w3c לא סיפקו מענה לבעיות html. 
אם היתה בעיה, היו פונים למפתחי הדפדפן, במקרה הזה המפתחים של Mosaic.

לאט לאט, התחילו לעלות הצעות להגדרת css שאיפשרו למפתחים וכותבים לעצב את הדף בצורה נוחה יותר ובמקביל פותחו גם חלופות - כלומר שפות עיצוב שונות מ-css, כאפשרות נוספת לעיצוב הדף (ישנן דוגמאות לקראת סוף המאמר בקישור - שימו לב לדימיון).
שפת עיצוב נוספת היתה DSSSL - שפותחה על ידי ISO להדפסת מסמכי SGML אך מסיבות שנראה בהמשך דווקא css היתה השפה הנכונה ביותר לעיצוב דפי אינטרנט. 

הפרדה

מאז ומתמיד היתה שאיפה בעולם הפיתוח ובעולם פיתוח האתרים בפרט ליצור הפרדה בין עיצוב הדף לבין תוכנו. 
אז למה שנרצה לעשות הפרדה? מה הבעיה עם תגיות html שייעודן עיצוב הדף?
כלומר, מה הבעיה למשל ביצירת טבלה עם צבע רקע כחול בצורה הזאת:

<table bgcolor="blue"> 
</table>
טוב, אולי בדוגמה הזו זה באמת לא נורא. אבל זה הופך להיות נורא כשזה מגיע למשהו כזה:



<table bgcolor="blue" border="4" cellpadding="5" cellspacing="10">
 <tr bgcolor="yellow">
  <td valign="top" align="center">
   This example meant to show you how <b>horrifying</b>
   <u>HTML <font color="green" size="7">text design</font> 
    can be</u>
  </td>
  <td>
   <table bgcolor="red" height="700" cellspacing="6" 
   cellpadding="10" border="0" width="800">
    <tr><td valign="center" bgcolor="navy">
     <font color="white" familily="Arial">White colored text</font> 
    </td><td><table width="400"><tr><td>Some text 1</td>
    <td height='40' width="70" valign="top">Some text 2</td><td>Some text 3</td>
    <td>Some text 4</td></tr><tr><td>Some text 1</td>
    <td>Some text 2</td><td>Some text 3</td><td>Some text 4</td></tr>
   </table></tr><tr><center><a href="http://gotosomesite.com">
   <img src="some_image.jpg" alt=""/></a></center></tr></table>
  </td><td></td><td></td><td></td></tr><tr bgcolor="white">
</tr><tr bgcolor="white"></tr></table> 

כמובן שבנוסף לכל הסיפור דאגתי גם לכך שהקוד בדוגמה לא יהיה מסודר אבל כשמדובר בhtml שמשמש גם לניהול תוכן וגם לעיצוב קשה להמנע מקוד לא מסודר - עכשיו נסו לשנות את צבע השורה הראשונה של הטבלה כולה לכתום ואת צבע רקע כל השורות האחרות לאפור ולבן. 
לא נעים. 

כעת חישבו על עורך התוכן, כלומר, אותו אחד שלא מעוניין לעצב את הדף אלא רק לעדכן את תוכנו, נניח שהוא רוצה רק לשנות את הטקסט באחד התאים. כמה קל יהיה לו למצוא את הטקסט שעליו לשנות? כמה קל יהיה לו לשנות את העיצוב בטעות?

באותה מידה, חישבו על המעצב, אותו אחד שלא מעוניין בתוכן הדף אלא רק בעיצובו - כמה קל לו לשנות את צבע כל הכותרות בדף - בהנחה שיש לא מעט כותרות? כמה קל לו לשנות את מיקום האלמנטים בדף? באיזו קלות הוא יכול למחוק או לשנות בטעות את התוכן באחד התאים? 

בנקודה הזאת אנחנו כבר צריכים להבין מדוע חשוב לשמור על הפרדה - חשבו על היתרון העצום ביצירת שני דפים - באחד נכתוב את מבנה הדף (שלד) ובשני נגדיר את העיצוב לשלד - בשני מקומות נפרדים לחלוטין. 
עכשיו הרבה יותר קל לעדכן את תוכן הדף ולשנות את העיצוב שלו.

מחלקות

ב-css יש לנו אפשרות להגדיר עיצוב אחד על אוסף של תגיות. למה הכוונה? נניח ואנחנו רוצים לשנות את גודל הגופן עבור כל הפסקאות בדף. אבל רק הפסקאות. 
בלי css היינו צריכים להוסיף את התגית font (הישנה והמיותרת) לכל אחת מהפיסקאות ולהוסיף לה את המאפיין המעדכן את גודל הגופן.
עם css נוכל לעשות זאת בשורה אחת - שורת קוד אחת שתשנה את צבע הרקע של כל הפיסקאות, גודל הגופן שלהן וסוג הגופן אם נרצה.
משנים את העיצוב של האתר? אין בעיה, משנים את אותה שורת קוד שכתבתנו לפני כן ומעדכנים את העיצוב בכל האתר.

לקוח

css נותן לנו את האפשרות ליצור עיצוב שונה עבור קוראים שונים. 
היום הגלישה לאינטרנט נעשית באמצעים רבים - אנחנו יכולים לגלוש באינטרנט באמצעות הדפדפן במחשב שלנו, באמצעות האייפון, האייפד, הטאבלט הטלויזיה ועוד. 
לכל אחד מהמכשירים הללו ישנם מאפיינים שונים - למשל, מסך מחשב (ברוב המקרים) יהיה גדול יותר ממסך טאבלט שיהיה גדול יותר ממסך של סמארטפון. 
במקרים רבים עיצוב אתר מסוים יתאים למסך המחשב האישי אך לא יתאים למסך הקטן של הסמארטפון. 
כשאנחנו סומכים על html בלבד, אנחנו דואגים שאותו עיצוב יופיע בכל אחד מהמכשירים, גם אם זה לא כל כך מתאים.
עם css נוכל להגדיר עיצוב שונה עבור כל אחד מהמכשירים מבלי לגעת בקוד ה-html של האתר. 

מה אם למשל היינו רוצים להגדיר שתי גירסאות לאתר? גירסת תצוגה וגירסת הדפסה? 
נוכל להגדיר שני עיצובים שונים לאתר - להגדירם כתצוגת מסך ותצוגת הדפסה ולתת לדפדפן לשלוח את הגרסה הנכונה למדפסת.

בקיצור, css מספק לנו דרך להציג ללקוח מספר עיצובים אפשריים ולאפשר לו לבחור את העיצוב המתאים לו ביותר (לקוח=דפדפן או מכשיר)

ישנן עוד סיבות רבות וטובות לשימוש ב-css, היום טכנולוגיה לעיצוב אתרים בלעדיה האתר שלנו יראה פשוט, ישן וזול..

22 בספט׳ 2012

טפסים ב HTML

במאמר הקודם ראינו כי שיטת GET היא לא בדיוק השיטה הכי טובה להעברת כמויות גדולות של מידע לשרת אינטרנט.

בעיה נוספת בהעברת פרמטרים לשרת היא הצורה שבה אנו מאפשרים למשתמש לשלוח את הנתונים, לא כל משתמש ינסה להירשם לאתר באמצעות הכתובת הבאה:

http://my_site.co.il/index.php?username=avner.cohen&password=123456&city_id=1&phone=050111111111

בבדיקה מהירה אפשר לראות כי הכתובת מכילה שם של קובץ ואחריו אוסף של משתנים עם ערכים, משורשרים באמצעות &.

מעבר לעובדה שהסיסמא חשופה, נרצה לספק למשתמש דרך קלה יותר להעברת נתונים ופחות מסורבלת (כל הסיפור קצת פחות נוח כשרוצים לשלוח כמות גדולה של מידע לשרת).
לשם כך html מספקת לנו אוסף תגיות ליצירת טפסים.

טפסי html הם אמצעי ויזואלי להעברת מידע לשרת, הנה דוגמה לטופס כזה:

טפסי HTML מספקים דרך נוחה לשליחת נתונים לשרת
רובנו משתמשים בטפסים דומים ביום יום, כשאנחנו נרשמים לאתר, כשאנחנו משלמים על מוצר באינטרנט, מגישים מועמדות למשרה מסוימת ועוד..

בהמשך נבנה את הטופס בדוגמה.

חשוב לציין, לפני שממשיכים שטפסים הם רק אמצעי לשליחת נתונים שונים באותו פורמט בדיוק, הנתונים שנשלחים לשרת הם צמדי מחרוזות - שם משתנה וערך, למשל:
firstname=yonatan
lastname=fishman
gender=male
city_id=31
...
הפקדים השונים מספקים לנו דרך נוחה לשליחת צמדי נתונים כאלה, עוזרים למשתמש למנוע טעויות ומספקים דרך לשליחת מספרי זיהוי בדרך נוחה יותר - מיד נבין למה הכוונה.

 התגית הראשונה שעלינו לזהות היא תגית >form< העוטפת את כל הפקדים ומאגדת אותם לטופס אחד:
<form action="target.aspx" enctype="application/x-www-form-urlencoded" method="post">
<!--רשימת פקדים-->
</form>
לתגית form המאפיינים הבאים:

  1. action - מציין את הדף אליו ישלחו נתוני הטופס, השרת לבדו לא יודע כיצד עליו לעבד את הנתונים (להוסיף משתמש חדש ל database? לעדכן משתמש קיים?), ולכן חייבים לכתוב קוד שיידע מה לעשות איתם, בדוגמה למעלה, הקוד שיקבל את הנתונים ימצא בדף target.aspx.
  2. method - השיטה שבה נשתמש לשליחת הנתונים, GET או POST (קיימות שיטות נוספות שעדיין לא נלמדו)
  3. enctype -  כיצד לקודד את הנתונים הנשלחים לשרת - ברירת המחדל היא "application/x-www-form-urlencoded", הממירה סימנים מיוחדים לקוד ascii ורווחים ל-"+". נשנה את ערך ברירת המחדל בעיקר כאשר נרצה להעלות קובץ, מאחר וקבצים לא מהווים מידע טקטואלי ושליחתם תיעשה ללא קידוד.
    הנה דוגמא לשליחת נתונים באמצעות קידוד: 

    username=Admin&
    password=%D7%9B%D7%A9%D7%9C%D7%A7%D7%A4%D7%A9%D7%93%D7%93&autologin=on&
    redirect=&query=&login=%D7%94%D7%AA%D7%97%D7%91%D7%A8

    שימו לב כי הערך במשתנה password אינו טקסט קריא מאחר והוא מקודד. 
בתוך התגית form נמקם את כל הפקדים.

התגית input
בתגית input נשתמש כדי ליצור את רוב הפקדים בדף.
נתחיל בפקד הבסיסי ביותר, textbox:
<form action="target.aspx" method="post">
  <p>
    <label for="firstname">First Name:</label>
    <input type="text" size="15" maxlength="30" name="firstname" 
title="Enter your first name" id="firstname" value="your name" />
  </p>
</form> 
התגית >label< מאפשרת יצירת תווית מקושרת - לתגית input נוסיף מאפיין id ואת התגית label נקשר אליה באמצעות המאפיין for. 

עכשיו כאשר נבחן את התגית input נבדיל בין מאפיינים המשותפים לכל הפקדים בטופס לבין מאפיינים הייחודיים לסוג מסוים של פקדים.
המאפיינים המשותפים לכל הפקדים הם: 
  1. name - למעשה המאפיין החשוב ביותר, מציין את שם המשתנה הנשלח לשרת (למשל: firstname). בניית הפקד היא לרוב חסרת טעם ללא מאפיין זה
  2. title - בעת מעבר עכבר מעל הפקד, יופיע tool tip עם ערך המאפיין title.
  3. value - ערך הפקד - כלומר הערך שיוצמד למשנה ב- name. במקרה של תיבת הטקסט, ערך זה יהיה בסופו של דבר, הטקסט אותו יכניס המשתמש לתיבה ( ה- value בתיבת הטקסט למעלה, הוא רק ערך ברירת המחדל בתיבת הטקסט, המשתמש יכול לשנות אותו בקלות).
  4. id - כל שם באנגלית המזהה את התגית באופן חד-ערכי. שתי תגיות או יותר לא יכולות לקבל את אותו ערך id 
  5. disabled - מאפיין המציג את הפקד בצבע אפור, מונע מן המשתמש לשנות את ערך הפקד.
    תגית המכילה את הערך disabled="disabled" לא תשלח את ערכה לשרת. 
המאפיינים האחרים של התגית מתארים אורך טקסט מקסימלי אותו יוכל להכניס המשתמש,  אורך תיבת הטקסט (בתוים) ומאפיין אחד נוסף וחשוב המתאר את סוג הפקד - type.

נציין אילו סוגי (type) פקדים קיימים:
  • password - מתנהג בדיוק אותו דבר כמו text מלבד העובדה שהטקסט מוסתר באמצעות נקודות או כוכביות.
  • reset - יוצר לחצן המאפשר למשתמש לאפס את תוכן הטופס - ברוב המקרים אין אנו משתמשים בפקד זה מאחר ולמשתמש אין צורך במחיקת הטופס, מה גם שלחיצה מקרית על הלחצן עלולה לגרום למחיקת כל הטופס ולעגמת נפש לא קטנה (כתבתם פוסט ארוך מאוד לפורום ובמקום לשלוח, איפסתם את הטופס. לא נעים)
  • submit - יוצר לחצן שליחה, בעת לחיצה על על הלחצן הדפדפן אוסף את נתוני הטופס ושולח לדף המופיע במאפיין action של הטופס. 
  • checkbox - יוצר תיבת סימון (v) בדף, במידה והמשתמש מסמן את התיבה - נשלח הערך המופיע ב value.

<p>
  <input type="checkbox" name="agreement" value="accept" id="agreement"/> 
  <label for="agreement">I Accept Site's</label> 
  <a href="http://notreally.com">Terms of Use</a>  
</p> 



  • radio - יוצר תיבת סימון, אך להבדיל מ- checkbox, מאפשר לבחור רק אפשרות אחת מתוך כמה, נוכל לשים יותר מקבוצת לחצי רדיו אחת וכדי לזהות קבוצה של לחצנים נשתמש באותו שם. בעת שליחת הטופס, ישלח לשרת השם שציינו והערך (value) של התיבה שנבחרה:
<p>
 <input type="radio" name="gender" checked="checked" value="male" id="gmale"/> 
 <label for="gmale">Male</label><br/>
 
 <input type="radio" name="gender" value="female" id="gfemale"/>
 <label for="gfemale">Female</label>
</p>

מלבד התגית input, ישנן שתי תגיות נוספות שונות בהן נשתמש:

התגית textarea
התגית textarea היא תגית מכולה המקבלת יותר משורת טקסט אחת - משמשת בעיקר ליצירת ועדכון הודעות ארוכות (מאמרים, הודעות דואר ועוד).
<p>
 About Me:<br/>
 <textarea name="about" id="about" cols="50" rows="10"></textarea>
</p>


התגית select ו option
התגית select יוצרת רשימת אפשרויות ומהווה מעין תחליף נוח לפקד radio כאשר ישנם הרבה אפשרויות מהן אפשר לבחור.

באמצעות select נוכל גם לאפשר למשתמש לבחור יותר מאפשרות אחת.

התגית select תכיל מספר תגיות option, אחת עבור כל אפשרות בחירה, כל תגית option תכיל מאפיין value שישלח לשרת עם ה- name שהצמדנו לתגית select.
מאפיין ה- size של התגית select מגדיר את גודל הרשימה - כאשר הגודל המינימלי הוא למעשה רשימה נפתחת. בדוגמא למטה size="4" מציג את select כרשימה עם פסי גלילה המציגה 4 פריטים.

בדרך כלל, נשמור במסד הנתונים מספר מזהה עבור כל ישות - או אוביקט, במקרה הבא, נשמור קוד מזהה עבור כל מקצוע, את הקוד המזהה נשלח באמצעות הטופס לשרת.
לא תמיד אותו קוד (לרוב מספרי) מובן למשתמש - למשל המספר 14 יכול לזהות את המקצוע Web Developer ולכן, במידה והמשתמש יבחר במקצוע זה, ארצה לשלוח לשרת את הצמד professions=14.
הבעיה היא שהמשתמש לא יודע שאותו מספר מזהה את המקצוע, אבל כן יבין את המקצוע "Web Developer", לכן כאשר נשתמש בתגית option נשים את המספר המזהה כערך value ואת שם המקצוע בתוך התגית, שיופיע בצורה ברורה למשתמש.

<p>
 Professions (Can select more than one):
 <select name="professions" size="4" multiple="multiple">
  <option value="webdev">Web Developer</option>
  <option value="netprog">.NET Programmer</option>
  <option value="phpexp">PHP Expert</option>
  <option value="cssdesigner">CSS Designer</option>
  <option value="flashanim">Flash Animator</option>
 </select>
</p>

  

בדוגמה למעלה, במידה והמשתמש יבחר באפשרות CSS Designer, הקוד שישלח לשרת יהיה cssdesigner.

הקוד המלא:
<!DOCTYPE html>
<html>
 <head>
  <title>Forms Page</title>
 </head>
 <body>
  <h1>Registration Form</h1>
  <form action="target.aspx" method="post">

   <p>
    <label for="firstname">First Name:</label>
    <input type="text" size="15" maxlength="30" name="firstname" 
     title="Enter your first name" id="firstname" />
   </p>
   <p>
    <label for="lastname">Last Name:</label>
    <input type="text" size="15" maxlength="30" name="lastname" 
     id="lastname"/>
   </p>
   <p>
    <label for="password">Password:</label>
    <input type="password" name="password" id="password" maxlength="15"/>
   </p>

   <p>
    <label for="password_conf">Password Confirmation:</label>
    <input type="password" name="password_conf" 
     id="password_conf" maxlength="15"/>
   </p>
   <p>
    <label for="email">Email Address:</label>
    <input type="text" name="email" id="email" 
     value="example@domain.com"/>
   </p>
   <p>
    Just a demo for a disabled field:
    <input type="text" disabled="disabled" name="disabled_field" 
     value="Will not be sent"/>
    <br/>

    Just a demo for read only field:
    <input type="text" readonly="readonly" name="readonly_field" 
     value="Will be sent"/>
   </p>
   <p>
    <fieldset>
     <legend>Gender</legend>
     <input type="radio" name="gender" checked="checked" 
      value="male" id="gmale"/> 
     <label for="gmale">Male</label><br/>
     
     <input type="radio" name="gender" value="female" id="gfemale"/>
     <label for="gfemale">Female</label>
    </fieldset>
   </p> 
   <p>
    Country of Residence:
    <select name="country">
     <option value="israel">Israel</option>
     <option value="germany">Germany</option>
     <option value="france">France</option>
     <option value="usa" selected="selected">
      United States of America
     </option> 
     <option value="canada">Canada</option>
    </select>
   </p> 
   <p>
    Professions (Can select more than one):
    <select name="professions" size="4" multiple="multiple">
     <option value="webdev">Web Developer</option>
     <option value="netprog">.NET Programmer</option>
     <option value="phpexp">PHP Expert</option>
     <option value="cssdesigner">CSS Designer</option>
     <option value="flashanim">Flash Animator</option>
    </select>
   </p>
   <p>
    About Me:<br/>
    <textarea name="about" id="about" cols="50" rows="10"></textarea>
   </p>
   <p>
    <input type="checkbox" name="agreement" val="accept" id="agreement"/>
    <label for="agreement">I Accept Site's</label> 
    <a href="http://notreally.com">Terms of Use</a>
   </p>
   <p>
    <input type="submit" value="Register!" name="reg_submit"/>
    <input type="reset" value="Clear Form"/>
   </p>
   
  </form>
 </body>
</html>

21 בספט׳ 2012

מבוא לטפסים ב-HTML

עד עכשיו ראינו דרך אחת בה הדפדפן “מדבר” עם השרת – על ידי בקשת get.

בכל פעם שרצינו לגשת לדף מסוים, הכנסנו כתובת URL לדפדפן ומאותו רגע, הדפדפן איתר את שרת האינטרנט, שלח לו בקשה וקיבל דף אינטרנט בחזרה.
הנה דוגמא לבקשה כזו
SNAGHTML2fdd854
בדוגמא למעלה אפשר לראות בקשת http שנשלחה מהדפדפן שלנו (Maxthon במקרה שלנו) לשרת האינטרנט.
נביט על השורה השלישית (השורה האפורה) ונראה כי הבקשה היא בקשת GET ותוכנה:
Expert Info (Chat/Sequence): GET /webhp?client=aff-maxthon-newtab&channel=t2 HTTP/1.1\r\n

כאשר אנו רוצים להעביר בקשה לעמוד מסוים או להעביר מילים למנוע חיפוש, נעביר בדרך כלל בקשות קצרות,
בקשות GET מאוד נוחות לשליחת כמויות קטנות של מידע, כמו למשל בקשה לקובץ מסוים על השרת או מספר מילים למנוע חיפוש (חפשו מילה בגוגל ותראו את הבקשה בשורת הכתובת).
אך כיצד נוכל להעביר כמות גדולה של מידע לשרת אינטרנט?  
איך נעביר למשל פרסום סטאטוס מאוד ארוך בפייסבוק? באמצעות GET? 

דבר אחד חשוב לגבי בקשות GET הוא העובדה שבקשות אלו מוגבלות באורכן, על פי ה- RFC:

The HTTP protocol does not place any a priori limit on the length ofa URI. Servers MUST be able to handle the URI of any resource theyserve, and SHOULD be able to handle URIs of unbounded length if theyprovide GET-based forms that could generate such URIs. A serverSHOULD return 414 (Request-URI Too Long) status if a URI is longerthan the server can handle (see section 10.4.15). 
Note: Servers should be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations may not properly support these lengths.
 

כלומר, על פי הפרוטוקול, שרת אינטרנט אמור לקבל בקשות GET בכל אורך, אך בפועל דפדפנים ישנים ושרתי PROXY מסוימים אינם מסוגלים להתמודד עם בקשות GET שאורכן עולה על 255 תווים.
שרתי אינטרנט מודרניים לעומת זאת, מאפשרים למנהל הרשת להגדיר את הגודל המקסימלי של בקשות ה-GET (בדרך כלל 8KB).

תכונה נוספת לשליחת מידע באמצעות GET היא הצגת הפרמטרים או הבקשה בשורת הכתובת, לא תמיד נרצה להעביר מידע דרך שורת הכתובת (איך נעביר סיסמת login לאתר?).
תכונה זו תהיה שימושית לשליחת / שמירת לינקים (כי תמיד נוכל להעתיק את הכתובת מהדפדפן), אך תהיה בעייתית במידה ונרצה "להסתיר" חלק מהמידע.

בקיצור, לעיתים קרובות, לא נוכל לסמוך על הדפדפן / שרתים שבדרך שיעבירו מידע רב באמצעות בקשת GET ולא תמיד נרצה שהמידע יוצג בשורת הכתובת של הדפדפן.

לכן נרצה להשתמש בשיטה שונה לשליחת מידע רב - POST (ישנה גם מתודולוגית הREST עליה עדיין לא דיברנו).