File:  [mozdev] / books / www / docbook / ch04.xml
Revision 1.5: download - view: text, annotated - select for diffs - revision graph
Tue Apr 22 14:28:44 2003 UTC (16 years, 7 months ago) by david
Branches: MAIN
CVS tags: HEAD
making corrections

    1: <chapter label="4" id="mozilla-CHP-4">
    3: <title>CSS in Mozilla Applications</title>
    6: <para>This chapter describes how Cascading Style Sheets (CSS) are used to
    7: create the look and feel of a Mozilla application's
    8: interface. Although XUL has a central role in creating a structure
    9: for an application's interface, defining widgets and
   10: their functionality, and creating the basic application code, it is
   11: CSS that creates the visible portion of an application. XUL and CSS
   12: often work so closely together that they seem inseparable, but XUL is
   13: generally responsible for the structure of an
   14: application's interface and CSS is responsible for
   15: the application's presentation. As described in the
   16: next sections, it is not until an XPFE application has been
   17: "skinned," or styled with
   18: stylesheets, that it has a usable interface.
   19: </para>
   21: <para>The first few sections in this chapter provide basic information
   22: about using CSS and some examples of how the Mozilla interface is
   23: created. They include reference material you can refer back to as you
   24: learn more. Starting with the "Creating New
   25: Skins" section, you can dive in, have some fun with
   26: CSS, and begin to create your own skins. The xFly package example
   27: created earlier in the book shows how to add custom styles to the XUL
   28: files you created in Chapters <link linkend="mozilla-CHP-2">Chapter 2</link> and <link linkend="mozilla-CHP-3">Chapter 3</link>. 
   29: </para>
   32: <sect1 role="" id="mozilla-CHP-4-SECT-1" label="4.1">
   33: <title>Interface Basics</title>
   35: <para>Before describing the
   36: <indexterm id="IXT-4-1156"><primary>interfaces</primary><seealso sortas="zz(see also user interface)">user
   37: interface</seealso></indexterm><indexterm id="IXT-4-1157"><primary>user
   38: interface</primary><secondary>overview</secondary></indexterm>
   39: <indexterm id="IXT-4-1158"><primary>UI</primary><see>user
   40: interface</see></indexterm>practice of using <indexterm id="IXT-4-1159"><primary>CSS
   41: (Cascading Style Sheets)</primary><secondary>user
   42: interfaces</secondary></indexterm>CSS, let's get
   43: some basic theory out of the way. When we talk about the interface of
   44: an application, we mean all of the parts of the application that are
   45: displayed and allow the user to interact. Buttons, windows, pages,
   46: menus, sliders, and descriptive text are all parts of the interface.
   47: In Mozilla, XUL usually defines the basic structure of the interface
   48: and CSS defines its presentation. These two aspects of the
   49: interface -- the way it's organized and the way
   50: it's presented -- are kept as distinct from one
   51: another as possible in Mozilla and in many good programming
   52: environments. Indeed, this separation is what gives rise to the
   53: concept of
   54: <indexterm id="IXT-4-1160"><primary>skins</primary></indexterm><indexterm id="IXT-4-1161"><primary>user
   55: interface</primary><secondary>skins</secondary></indexterm>skins -- coherent,
   56: separate, and typically swappable
   57: "looks" for the same underlying
   58: structure. Mozilla uses Cascading Style Sheets, a quickly evolving
   59: series of standards already common in HTML web page presentation, to
   60: define the skin of XUL application interfaces.
   61: </para>
   63: <sect2 role="" id="mozilla-CHP-4-SECT-1.1" label="4.1.1">
   64: <title>Skins Versus Themes</title>
   66: <para>When we <indexterm id="IXT-4-1162"><primary>skins</primary><secondary>compared to
   67: themes</secondary></indexterm><indexterm id="IXT-4-1163"><primary>themes</primary><secondary>compared
   68: to skins</secondary></indexterm><indexterm id="IXT-4-1164"><primary>user
   69: interface</primary><secondary>skins</secondary><tertiary>compared to
   70: themes</tertiary></indexterm>say <emphasis>skin</emphasis> in
   71: this<indexterm id="IXT-4-1165"><primary>CSS (Cascading Style
   72: Sheets)</primary><secondary>skins</secondary><tertiary>themes
   73: and</tertiary></indexterm> chapter, we refer to the look of the
   74: interface -- to the CSS styles and its relationship to the XUL
   75: structure underneath. The term <emphasis>theme</emphasis> is also
   76: used often in conjunction with interfaces and skins. These words are
   77: used interchangeably, although there are some differences in their
   78: meaning.
   79: </para>
   81: <para>A single, overall theme is made up of many skins. The Navigator
   82: component's skin described in
   83: <filename>navigator.css</filename><indexterm id="IXT-4-1166"><primary>navigator.css</primary></indexterm>,
   84: for example, is part of the overall Modern theme of Mozilla.
   85: Following this definition, the Modern theme may be made up of as many
   86: as 20 or 30 different skins corresponding to the major components and
   87: major UI features within those components. In addition to
   88: <emphasis>navigator.css</emphasis>, for example, there are
   89: stylesheets for <emphasis>toolbar.css</emphasis>,
   90: <emphasis>linkToolbar.css</emphasis>, and others, which collectively
   91: make up the Navigator skin. The CSS files may also be described as
   92: skins, as when this book instructs you to "open the
   93: <filename>messenger.css</filename> skin in a text
   94: editor." All skins of a particular kind or look
   95: organized together comprise a single theme.
   96: </para>
   98: <para>Themes are also often used to refer to the different looks that you
   99: can download and install for Mozilla and Netscape 6.x and 7.x. (To
  100: get new themes for the Mozilla browser go to View &gt;
  101: Apply Themes &gt; Get New Themes.) Any application
  102: created with Mozilla, though, can have different themes that users
  103: can install and select to customize the look of that application.
  104: </para>
  106: <para>This distinction between a skin and a theme is not enforced -- or
  107: even acknowledged -- by many people in the Mozilla community, so
  108: you will see a profligate use of these terms in practice. Try to
  109: remain calm. The terminology differences aren't
  110: important. What is important is that you can create one (or many)
  111: looks for your application using CSS. This chapter will show you how.
  112: </para>
  114: </sect2>
  115: <sect2 role="" id="mozilla-CHP-4-SECT-1.2" label="4.1.2">
  116: <title>Limitations of a Skin</title>
  118: <para>Skins are used
  119: <indexterm id="IXT-4-1167"><primary>skins</primary><secondary>limitations
  120: of</secondary></indexterm><indexterm id="IXT-4-1168"><primary>user
  121: interface</primary><secondary>skins</secondary><tertiary>limitations
  122: of</tertiary></indexterm>to style the structure of an interface that
  123: has been created with XUL. Once the interface has been defined in
  124: XUL, that structure is set and CSS can be used to change how that
  125: structure will look, but can't be used to change the
  126: structure itself. In practice, this means that you can use CSS to
  127: change the way a button looks  --  but to move a button from one
  128: toolbar to another within the interface, you need to edit your XUL
  129: code. Skins generally affect the usability or appearance, but not the
  130: functionality of an interface, though the use of XBL in CSS is an
  131: exciting exception to this rule, as you will see.
  132: </para>
  134: <para>This separation of the style and the content of an application means
  135: that there are a number of things you can't change
  136: in an application using CSS. Here are some examples of the kinds of
  137: interface elements that cannot be manipulated with a skin.
  138: </para>
  140: <itemizedlist><listitem>
  141: <para>The position and contents of menus and menu items and the
  142: functionality they trigger.
  143: </para>
  144: </listitem><listitem>
  145: <para>The overall layout and functionality of buttons.</para>
  146: </listitem><listitem>
  147: <para>The general layout of the application (although you can use CSS to
  148: hide sections of an interface).
  149: </para>
  150: </listitem></itemizedlist>
  151: <para>While the underlying structure of menus and buttons cannot be changed
  152: in the process of editing a theme, you can, of course, change the
  153: appearance of things quite radically. In fact, you can change whether
  154: an element -- say, an item in a menu -- has any visibility
  155: using the <literal>visibility</literal> or <literal>display</literal>
  156: CSS properties. One of the Mozilla extensions to CSS,
  157: <literal>-moz-box-ordinal</literal>, lets you set the order in which
  158: the elements in a container are displayed. We describe these
  159: extensions and others later in this chapter in the section <link linkend="mozilla-CHP-4-SECT-2.3">Section 4.2.3</link>. 
  160: </para>
  162: </sect2>
  163: <sect2 role="" id="mozilla-CHP-4-SECT-1.3" label="4.1.3">
  164: <title>Theme Abstraction (or Building Good Skins)</title>
  166: <para>One of the
  167: most<indexterm id="IXT-4-1169"><primary>themes</primary><secondary>creating, design
  168: considerations</secondary></indexterm><indexterm id="IXT-4-1170"><primary>skins</primary><secondary>creating</secondary><tertiary>design
  169: considerations</tertiary></indexterm> important
  170: <indexterm id="IXT-4-1171"><primary>design issues, user
  171: interfaces</primary><secondary>themes and
  172: skins</secondary></indexterm>parts of a well-written theme is that it
  173: be as separate as possible from the actual structure of the
  174: interface -- that it be abstracted as a layer so it can be
  175: switched or updated without affecting or forcing you to edit the
  176: underlying XUL. Keeping an application's style
  177: separate is not mandatory, however, and you can have all presentation
  178: code in your XUL files, although we explain why this
  179: isn't a good idea.
  180: </para>
  182: <para>As we have tried to stress, at the most basic level, abstraction
  183: means that the XUL should describe the structure and the CSS should
  184: describe the presentation, or look, of the interface. In reality, of
  185: course, the presentation layer is itself divided into different
  186: layers, where lower, more basic files like
  187: <emphasis>xul.css</emphasis> describe the look and feel of common UI
  188: elements such as buttons and menus, and higher-level CSS files
  189: consistently describe the layout and stylistic details of a
  190: component. When working on a theme or skin for your application, you
  191: should use as few inline style attributes as you can, as well as
  192: ensure that your themes are organized into component subdirectories
  193: and that one skin does not depend on another that is farther down in
  194: the "skin hierarchy." (This is
  195: discussed later in this chapter in the <link linkend="mozilla-CHP-4-SECT-3.1">Section 4.3.1</link> section.).
  196: </para>
  198: <sidebar id="mozilla-CHP-4-SIDEBAR-1">
  199: <title>Planning Your Interface</title>
  201: <para>Before you begin <indexterm id="IXT-4-1172"><primary>user
  202: interface</primary><secondary>planning
  203: considerations</secondary></indexterm>using CSS and images to style
  204: your XUL application code, it's important to have a
  205: sense of where your interface is heading. Begin by asking yourself
  206: some questions. What should the buttons look like? Do you want to
  207: give users the ability to switch skins in your application, as they
  208: can in the Mozilla browser? How will your application be affected
  209: when the user switches skins in Mozilla? What, if any, are the
  210: differences on the different platforms on which you expect users to
  211: run your application?
  212: </para>
  214: <para>Although creating interfaces using XUL and CSS is fun and fast,
  215: it's best to do a mockup of your interface before
  216: you begin so you know where you are heading (both Adobe Photoshop and
  217: the GIMP are excellent tools for creating sophisticated images and
  218: mock-ups). The creators of the Modern and Classic themes do lots of
  219: visualization of the themes in image editing software and go through
  220: several iterations of testing and feedback.
  221: </para>
  223: <para>One of the great advantages of using such an approach is that you
  224: will undoubtedly develop images and icons for your interface anyway,
  225: and you can slice and dice your mockup to get, for example, the icons
  226: for your buttons, the background images, and other real parts of the
  227: interface. You may find that you can actually use most of the mockup
  228: in your actual interface! See <link linkend="mozilla-CHP-4-SECT-2.4">Section 4.2.4</link> later in this chapter for an
  229: explanation of how this image slicing can work in an advanced way
  230: when you have XBL-based widgets that use GIF images that are stitched
  231: together.
  232: </para>
  234: <para>Because the overall theme of an application will most likely consist
  235: of a large number of individual graphic elements and widgets, pay
  236: special attention to considerations of color palette, web-optimized
  237: file formats such as <filename>.gif</filename> and
  238: <filename>.png</filename>, and file size to make sure your interface
  239: looks good and loads quickly.
  240: </para>
  241: </sidebar>
  243: </sect2>
  244: <sect2 role="" id="mozilla-CHP-4-SECT-1.4" label="4.1.4">
  245: <title>Cross-Platform Interface Considerations</title>
  246: <indexterm class="startofrange" id="mozilla-IDXTERM-505"><primary>Cross-Platform</primary><secondary>interface considerations</secondary></indexterm>
  248: <para>Often in <indexterm class="startofrange" id="mozilla-IDXTERM-506"><primary>user
  249: interface</primary><secondary>design issues, cross-platform
  250: considerations</secondary></indexterm><indexterm class="startofrange" id="mozilla-IDXTERM-507"><primary>design issues, user
  251: interfaces</primary><secondary>cross-platform
  252: considerations</secondary></indexterm>traditional interface
  253: development, you try to make things look and work right on a single
  254: platform. Using something like MFC on Windows, for example, you can
  255: drop in the widget it provides and be reasonably assured that the
  256: interface will look like a Windows application interface whenever and
  257: wherever your application is run.
  258: </para>
  260: <para>When you do cross-platform
  261: <indexterm id="IXT-4-1173"><primary>Cross-Platform</primary><secondary>user interface
  262: development</secondary></indexterm>user interface development, you
  263: need to be aware of how your application will look on the platforms
  264: on which it will be used. One common difference, for example, is the
  265: layout of scrollbars in Windows applications and in Macintosh
  266: applications. On Windows, scrollbars typically have buttons at either
  267: end that advance the scrollbar button itself. On the classic
  268: Macintosh, the scrollbars are configured so that the buttons are
  269: clustered together. The difference is subtle, but it is a source of
  270: huge contention in the Mozilla world. <link linkend="mozilla-CHP-4-FIG-1">Figure 4-1</link>
  271: shows the difference between the scrollbars on the two platforms.
  272: (This figure also shows a small notch in the lower righthand corner
  273: that is part of all classic Macintosh application windows and that
  274: shifts part of the Mozilla interface over to the left.)
  275: </para>
  277: <figure id="mozilla-CHP-4-FIG-1" label="4-1">
  278: <title>Scrollbars on Windows and on the Macintosh</title>
  279: <graphic fileref="figs/moz_0401.png"/></figure>
  281: <para>When you use the
  282: <indexterm id="IXT-4-1174"><primary>Cross-Platform</primary><secondary>XPFE</secondary></indexterm><indexterm id="IXT-4-1175"><primary>XPFE</primary><secondary>user
  283: interface cross-platform considerations</secondary></indexterm>XPFE,
  284: you use a single code base to deploy on any number of different
  285: platforms. In the Mozilla code, there are some tricks for making
  286: things work differently on different platforms. Like scrollbars, the
  287: layout of buttons in dialogs is another important area of platform
  288: difference. The layout code for the Open Web Location dialog, for
  289: example, is defined in platform-specific files, and slightly
  290: different dialog layouts are deployed transparently to users
  291: (depending on their platform). <link linkend="mozilla-CHP-4-FIG-2">Figure 4-2</link>
  292: illustrates the differing layouts of this dialog on different
  293: platforms (note the different positions of the Open and Cancel
  294: buttons in the two images).
  295: </para>
  297: <figure id="mozilla-CHP-4-FIG-2" label="4-2">
  298: <title>The Open Web Location dialog in Windows and the Macintosh</title>
  299: <graphic fileref="figs/moz_0402.png"/></figure>
  301: <para>If you look in the global resources area of the
  302: <filename>xpfe</filename> in the source code (using a tool like
  303: Mozilla's LXR), you can see the platform
  304: subdirectories where the buttons in the dialogs are arranged with
  305: <literal>&lt;spacer /&gt;</literal> <indexterm id="IXT-4-1176"><primary>spacer
  306: element, XUL</primary><secondary>user interface cross-platform
  307: considerations</secondary></indexterm>elements and different
  308: alignments:
  309: </para>
  311: <programlisting>mozilla/xpfe/global/resources/content/
  312:   mac/
  313:     platformDialogOverlay.xul
  314:   os2/
  315:     platformDialogOverlay.xul
  316:   unix
  317:     platformDialogOverlay.xul
  318:   win
  319:     platformDialogOverlay.xul</programlisting>
  321: <para>These platform-specific files allow the application developer to
  322: write XUL that works the same way on every platform, but preserves
  323: subtler aspects of an interface that users expect from
  324: their<indexterm id="IXTR3-1294" class="endofrange" startref="mozilla-IDXTERM-506"/><indexterm id="IXTR3-1295" class="endofrange" startref="mozilla-IDXTERM-507"/> <indexterm id="IXTR3-1296" class="endofrange" startref="mozilla-IDXTERM-505"/>platform. 
  325: </para>
  327: </sect2>
  328: </sect1>
  330: <sect1 role="" id="mozilla-CHP-4-SECT-2" label="4.2">
  331: <title>Introduction to CSS in Mozilla</title>
  333: <para>Now that you have absorbed some of the most important basic aspects
  334: of interface design, we can begin to discuss how Mozilla uses CSS and
  335: images to make actual interfaces out of the structure defined in the
  336: XUL files. Though XUL contains the widgets and structure upon which
  337: the interface rests, it is not until at least some basic skin
  338: information has been loaded into the XUL that the interface becomes
  339: visible and editable by the user. In addition to this, CSS binds XBL
  340: widgets to the basic structure of the XUL code, allowing extended
  341: content to appear in your document. For more information about XBL,
  342: see <link linkend="mozilla-CHP-7">Chapter 7</link>.
  343: </para>
  345: <sect2 role="" id="mozilla-CHP-4-SECT-2.1" label="4.2.1">
  346: <title>Basic XUL + CSS Interaction</title>
  348: <para>XUL and CSS interact at two basic levels in Mozilla. At the file
  349: level, XUL picks up CSS information by explicitly loading CSS
  350: stylesheets at runtime. At the element level, selectors bind CSS
  351: rules to specific XUL elements or groups of elements. For an XUL
  352: element to pick up a style defined in a CSS file, the XUL file must
  353: load the CSS file, and an element or group of elements in the XUL
  354: must match a selector in the CSS rule. We discuss these basic levels
  355: of interaction in the following two sections.
  356: </para>
  358: <sect3 role="" id="mozilla-CHP-4-SECT-2.1.1" label="">
  359: <title>CSS and XUL file interaction</title>
  361: <para>Like HTML, <indexterm id="IXT-4-1177"><primary>CSS (Cascading Style
  362: Sheets)</primary><secondary>XUL</secondary><tertiary>file
  363: interaction</tertiary></indexterm><indexterm id="IXT-4-1178"><primary>XUL (XML-based
  364: User-interface
  365: Language)</primary><secondary>CSS</secondary><tertiary>file
  366: interaction</tertiary></indexterm>XUL loads style information by
  367: including a specific processing instruction somewhere at the top of
  368: the file. There are various ways to apply style to HTML pages,
  369: including the common example below, in which a
  370: <indexterm id="IXT-4-1179"><primary>link element, loading
  371: stylesheets</primary></indexterm><literal>&lt;link /&gt;</literal>
  372: element with a URI loads an external stylesheet that holds the style
  373: information for the web page.
  374: </para>
  376: <programlisting>&lt;link rel="stylesheet" href="../style.css" type="text/css"&gt;</programlisting>
  378: <para>In XUL, however, you must use one or more special processing
  379: instructions at the top of the XUL file to load
  380: the<indexterm id="IXT-4-1180"><primary>stylesheets</primary><secondary>loading</secondary></indexterm><indexterm id="IXT-4-1181"><primary>CSS
  381: (Cascading Style Sheets)</primary><seealso sortas="zz(see also style sheets)">stylesheets</seealso></indexterm> CSS stylesheet
  382: information, or skin, into the XUL.
  383: </para>
  385: <programlisting>&lt;?xml-stylesheet href="chrome://global/skin" type="text/css"?&gt;</programlisting>
  387: <para>Note that the XUL<indexterm id="IXT-4-1182"><primary>URLs (Universal Resource
  388: Locators)</primary><secondary>stylesheet
  389: loading</secondary></indexterm> stylesheet loading supports the use
  390: of <literal>http://</literal> and <literal>file://</literal> type
  391: URLs, but most often,
  392: the<indexterm id="IXT-4-1183"><primary>chrome</primary><secondary>URLs, stylesheet
  393: loading</secondary></indexterm> <literal>chrome://</literal> type URL
  394: is used, which points to files that are available in the
  395: application's chrome subdirectory and that are
  396: registered with the chrome registry. The example above uses a special
  397: feature of this chrome type URL, which resolves directory pointers to
  398: files within those directories that have the same name as the
  399: directory itself (thus serving as a shorthand for main theme
  400: stylesheets). The chrome URL <literal>chrome://global/skin</literal>,
  401: in other words, loads a stylesheet found at
  402: <literal>chrome://modern.jar:/global/skin/global.css</literal>.
  403: </para>
  407: <tip id="ch04-4-fm2xml" role="ora">
  408: <para>XUL also supports the <indexterm id="IXT-4-1184"><primary>inline
  409: styles</primary></indexterm><indexterm id="IXT-4-1185"><primary>stylesheets</primary><secondary>inline
  410: styles</secondary></indexterm>use of <firstterm>inline
  411: styles</firstterm>, which is style information that is applied to
  412: individual elements with a style attribute. However, this practice is
  413: generally frowned upon, since it overrides the skin information and
  414: makes it very difficult for new skins to be applied correctly.
  415: </para>
  416: </tip>
  418: <para>Actually, the chrome URL in the example does more than this. Another
  419: important function of the chrome registry is that it keeps track of
  420: which packages you have installed, which skin you have applied to
  421: your application, and resolves URLs like
  422: <literal>chrome://global/skin</literal> into the global skin
  423: information for the currently selected skin. If you apply the modern
  424: skin, for example, then this URL loads the global skin file from the
  425: <filename>modern.jar</filename>; if you apply the Classic skin, then
  426: the chrome URL actually resolves to
  427: <literal>chrome://classic.jar:/global/skin/global.css</literal>
  428: instead. This flexibility in the chrome registry abstracts the
  429: structure in the XUL files from the skin information and allows you
  430: to create and apply different skins.
  431: </para>
  433: </sect3>
  435: <sect3 role="" id="mozilla-CHP-4-SECT-2.1.2" label="">
  436: <title>Applying style rules to XUL</title>
  438: <para>In CSS, <indexterm id="IXT-4-1186"><primary>CSS (Cascading Style
  439: Sheets)</primary><secondary>selectors</secondary></indexterm><indexterm id="IXT-4-1187"><primary>selectors,
  440: CSS</primary></indexterm><emphasis>selector</emphasis>
  441: <indexterm id="IXT-4-1188"><primary>CSS (Cascading Style
  442: Sheets)</primary><secondary>XUL</secondary><tertiary>applying style
  443: rules</tertiary></indexterm><indexterm id="IXT-4-1189"><primary>XUL (XML-based
  444: User-interface
  445: Language)</primary><secondary>CSS</secondary><tertiary>applying style
  446: rules</tertiary></indexterm>refers to the element or group of
  447: elements to which a style rule is bound -- to the thing that is
  448: selected for styling. In some cases, the selector is an actual XUL
  449: element. The following style rule, for example, says that all XUL
  450: <literal>&lt;menu/&gt;</literal> elements in the XUL file(s) into
  451: which this CSS is loaded will have a red background color:
  452: </para>
  454: <programlisting>menu {
  455:   background-color: red;
  456: }</programlisting>
  458: <para>In this case, the element selector names an element (menu) directly:
  459: all elements of that type match and are styled with the rule. In the
  460: next few sections, we describe the main types of selectors and the
  461: style rules that can be applied to them. With a couple of notable
  462: exceptions (see <link linkend="mozilla-CHP-4-SECT-2.3">Section 4.2.3</link> later
  463: in this chapter), the CSS you use with XUL is the same one you use
  464: for HTML elements.
  465: </para>
  467: </sect3>
  469: <sect3 role="" id="mozilla-CHP-4-SECT-2.1.3" label="">
  470: <title>Inline styles</title>
  472: <para>Another way to <indexterm id="IXT-4-1190"><primary>CSS (Cascading Style
  473: Sheets)</primary><secondary>XUL</secondary><tertiary>inline
  474: styles</tertiary></indexterm><indexterm id="IXT-4-1191"><primary>XUL (XML-based
  475: User-interface
  476: Language)</primary><secondary>CSS</secondary><tertiary>inline
  477: styles</tertiary></indexterm>apply style to XUL elements is to use
  478: inline style rules. Use inline styles with caution. All XUL elements
  479: have a <literal>style</literal> attribute that can be used to define
  480: styles directly for that element. In the following example, the
  481: <literal>style</literal> attribute is used (in a common but somewhat
  482: deprecated manner) to hide the XUL element -- to apply a style
  483: that suppresses rendering of the element (though it still takes up
  484: space in the UI):
  485: </para>
  487: <programlisting>&lt;menuitem id="e_src" 
  488:   label="&amp;editsrc.label;"
  489:   <userinput>style</userinput>="visibility: none;" /&gt;</programlisting>
  491: <para>When you use inline styles, the syntax does not include the brackets,
  492: but you can still add multiple style rules by using the semicolon.
  493: The item before the colon is the property, and the item after it is
  494: its value. The format of inline styles is as follows:
  495: </para>
  497: <programlisting>style="style attribute1: value[; style attribute2: value; etc...]"</programlisting>
  499: <para>The reason why inline styles are frowned upon in XUL and skin
  500: development is that they can be extremely difficult to locate and
  501: work around when you design a new skin and want to change the
  502: appearance of an element that has an inline style. The style
  503: attribute takes precedence over styles applied from other
  504: sources -- inline styles are the last rule in the cascade of style
  505: rules -- so they cascade over styles defined in a skin and may
  506: "break" the overall look of that
  507: skin.
  508: </para>
  510: <para>Besides this problem, many tricks for which application developers
  511: use the inline style can be done using XUL attributes.
  512: It's very common to use the CSS attribute-value
  513: pairs <literal>display:</literal> <literal>none;</literal> or
  514: <literal>visibility:</literal> <literal>none;</literal> to hide
  515: elements in order to change what's available from
  516: the interface. However, smart XUL developers use the
  517: <literal>hidden</literal><filename> </filename>or the<filename>
  518: </filename><literal>collapse</literal> attribute instead, thereby
  519: keeping structural matters as separate from style matters as
  520: possible.
  521: </para>
  523: </sect3>
  524: </sect2>
  525: <sect2 role="" id="mozilla-CHP-4-SECT-2.2" label="4.2.2">
  526: <title>Stylesheet Syntax</title>
  528: <para>Cascading Style Sheets <indexterm class="startofrange" id="mozilla-IDXTERM-530"><primary>style
  529: definitions</primary></indexterm><indexterm class="startofrange" id="mozilla-IDXTERM-531"><primary>CSS (Cascading Style
  530: Sheets)</primary><secondary>style
  531: definitions</secondary></indexterm>are the blueprints for Mozilla
  532: skins. In Cascading Style Sheets, style definitions take the
  533: following basic form:
  534: </para>
  536: <programlisting>element { 
  537:   style attribute1: value; 
  538:   style attribute2: value; 
  539:   style attribute3: value; 
  540: }</programlisting>
  542: <para>For example, the following definition makes all XUL menus appear with
  543: a one-pixel border, a light-blue background, and ten-point fonts:
  544: </para>
  546: <programlisting>menu { 
  547:   border: 1px; 
  548:   background-color: lightblue; 
  549:   font-size: 10pt; 
  550: }</programlisting>
  552: <para>This is an example of using the element itself -- in this case, a
  553: "menu" -- as a selector (the
  554: item to which the style definition is applied). In addition to the
  555: basic element selector and style rules, CSS provides the application
  556: of style information to classes of elements, element IDs, and
  557: elements with particular attributes or states. The following three
  558: sections demonstrate the basic format for these three common style
  559: selectors.
  560: </para>
  562: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.1" label="">
  563: <title>The element selector</title>
  565: <para>The <emphasis>element</emphasis> <emphasis>selector</emphasis> is
  566: <indexterm id="IXT-4-1192"><primary>element selectors,
  567: CSS</primary></indexterm><indexterm id="IXT-4-1193"><primary>CSS (Cascading Style
  568: Sheets)</primary><secondary>selectors</secondary><tertiary>element</tertiary></indexterm><indexterm id="IXT-4-1194"><primary>selectors,
  569: CSS</primary><secondary>element</secondary></indexterm>the most basic
  570: kind of selector. It is just the name of the element to be styled at
  571: the front of the style rule. In the previous example, the
  572: <literal>&lt;menuitem /&gt;</literal> element, defined in a XUL file
  573: that loads this style rule, will have a light blue background color:
  574: </para>
  576: <programlisting>element { attribute: value; }
  577: menuitem  { background-color: lightblue; }</programlisting>
  579: </sect3>
  581: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.2" label="">
  582: <title>The pseudoelement selector</title>
  584: <para>The <emphasis>pseudoelement</emphasis> <emphasis>selector</emphasis>
  585: <indexterm id="IXT-4-1195"><primary>pseudoelement selectors,
  586: CSS</primary></indexterm><indexterm id="IXT-4-1196"><primary>CSS (Cascading Style
  587: Sheets)</primary><secondary>selectors</secondary><tertiary>pseudoelement</tertiary></indexterm><indexterm id="IXT-4-1197"><primary>selectors,
  588: CSS</primary><secondary>pseudoelement</secondary></indexterm>selects
  589: a piece of an element for styling. While a selector like
  590: <literal>menuitem</literal> picks up all menu items in a given XUL
  591: document, a pseudoelement selector like
  592: <literal>menuitem:first-letter</literal> binds the
  593: rule's styles to only the first letter in a
  594: <literal>menuitem</literal> value.
  595: </para>
  597: <programlisting>menuitem:first-letter { text-decoration: underline; }
  598: description:first-line { margin-left: .25in; }</programlisting>
  600: <para>The first style rule above gives all menu items to which it applies
  601: the look of being <literal>accesskey</literal> enabled. The second
  602: creates an indentation in the first line of a XUL
  603: <literal>description</literal> element's text. Menu
  604: access keys let you open and choose items from a menu by using the
  605: underlined letters and modifiers (e.g.,
  606: "F" and
  607: <literal>&lt;alt&gt;</literal> to open the File menu).
  608: </para>
  610: </sect3>
  612: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.3" label="">
  613: <title>The class selector</title>
  615: <para>The <emphasis>class selector</emphasis> <indexterm id="IXT-4-1198"><primary>class
  616: selectors, CSS</primary></indexterm><indexterm id="IXT-4-1199"><primary>CSS
  617: (Cascading Style
  618: Sheets)</primary><secondary>selectors</secondary><tertiary>class</tertiary></indexterm><indexterm id="IXT-4-1200"><primary>selectors,
  619: CSS</primary><secondary>class</secondary></indexterm>applies the
  620: style rule to all XUL widgets of a given class. In the XUL files that
  621: define the structure of Netscape 7, the class is specified with the
  622: <literal>class</literal> attribute (e.g., <literal>&lt;menu
  623: class="baseline"&gt;</literal>) and in CSS with the dot notation:
  624: </para>
  626: <programlisting>element.class { attribute: value;} 
  627: menu.baseline {   border: 0px;   font-size: 9pt; }</programlisting>
  629: <para>In this example, all menus with a XUL baseline class have no borders
  630: and a nine-point font size. Note that you can use the class without
  631: the preceding XUL element to skin all XUL elements with a given
  632: class. In <link linkend="mozilla-CHP-4-EX-1">Example 4-1</link>, both the XUL box and the XUL
  633: menu pick up the style given in the
  634: "redbox" class style definition.
  635: </para>
  637: <example id="mozilla-CHP-4-EX-1" label="4-1">
  638: <title>Class selector in CSS </title>
  639: <programlisting>.redbox {
  640:   border: 2px solid red;
  641:   font-size: 9pt;
  642: } 
  643: &lt;box class="redbox"&gt;
  644:     &lt;menu class="redbox"&gt;
  645:     &lt;menu class="bluebox"&gt;
  646: &lt;/box&gt;</programlisting>
  647: </example>
  649: </sect3>
  651: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.4" label="">
  652: <title>The ID selector</title>
  654: <para>The CSS <emphasis>ID selector</emphasis> <indexterm id="IXT-4-1201"><primary>CSS
  655: (Cascading Style
  656: Sheets)</primary><secondary>selectors</secondary><tertiary>ID</tertiary></indexterm><indexterm id="IXT-4-1202"><primary>selectors,
  657: CSS</primary><secondary>ID</secondary></indexterm>applies the style
  658: rule to a unique XUL element. As with <literal>class</literal>, the
  659: <literal>ID</literal> is specified in the XUL with an attribute
  660: (e.g., <literal>&lt;menu id="file_menu"&gt;</literal>) and in the CSS
  661: with the pound sign preceding the <literal>ID</literal> itself. In
  662: this example, the menu with an ID of <literal>edit</literal> has a
  663: red color:
  664: </para>
  666: <programlisting>element#id { attribute: value;} 
  667: menu#edit { color: red;}</programlisting>
  669: <para>In the example above, both the element type and the element ID are
  670: given. You can also identify elements anonymously (though still
  671: uniquely) by using just the selector:
  672: </para>
  674: <programlisting>#whitey {
  675:     background-color: white;
  676:     margin: .25in;
  677: }</programlisting>
  679: <para>In the case of IDs, these selectors are identical, since IDs need
  680: to be unique across the whole XUL file. When you use classes,
  681: however, the typeless style rule is a good way to apply your style
  682: information to a range of elements.
  683: </para>
  685: </sect3>
  687: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.5" label="">
  688: <title>The attribute selector</title>
  690: <para>The <emphasis>attribute selector</emphasis>
  691: <indexterm id="IXT-4-1203"><primary>attribute selectors,
  692: CSS</primary></indexterm><indexterm id="IXT-4-1204"><primary>CSS (Cascading Style
  693: Sheets)</primary><secondary>selectors</secondary><tertiary>attrribute</tertiary></indexterm><indexterm id="IXT-4-1205"><primary>selectors,
  694: CSS</primary><secondary>attribute</secondary></indexterm>allows you
  695: to style XUL elements with particular attributes or with attributes
  696: of a particular value. In <link linkend="mozilla-CHP-4-EX-2">Example 4-2</link>, all elements
  697: with a disabled attribute set to <literal>true</literal> will have a
  698: light-grey color.
  699: </para>
  701: <example id="mozilla-CHP-4-EX-2" label="4-2">
  702: <title>Attribute selector in CSS </title>
  703: <programlisting>element [attribute=value] { attribute: value; }
  704: element [attribute~=value] { attribute: value; }
  705: *[disabled="true"]   
  706: {     
  707:   color: lightgrey; 
  708: } 
  709: menu[value="File"] {
  710:   font-weight: bold;
  711: }
  712: [id~="my"] { color: red; }</programlisting>
  713: </example>
  715: <para>Note that <link linkend="mozilla-CHP-4-EX-2">Example 4-2</link> uses the <literal>*</literal>
  716: character for selecting all elements. This
  717: "wildcard" selector can be combined
  718: with attribute and other selectors to make a powerful filter in your
  719: CSS stylesheets -- but of course, in an example like <link linkend="mozilla-CHP-4-EX-2">Example 4-2</link>, it could be omitted and
  720: <literal>[disabled=true]</literal> would still apply to all elements
  721: with that attribute set to that value.
  722: </para>
  724: <para><link linkend="mozilla-CHP-4-EX-2">Example 4-2</link> also uses <literal>~=</literal> to match
  725: attributes that contain the given fragment. In this case, any
  726: elements that have an ID with the fragment
  727: "my" have text colored red, as when
  728: you want to see all your customized elements for debugging purposes.
  729: </para>
  731: </sect3>
  733: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.6" label="">
  734: <title>Pseudoclass selectors</title>
  736: <para>Another <indexterm id="IXT-4-1206"><primary>pseudoclass selectors,
  737: CSS</primary></indexterm><indexterm id="IXT-4-1207"><primary>CSS (Cascading Style
  738: Sheets)</primary><secondary>selectors</secondary><tertiary>pseudoclass</tertiary></indexterm><indexterm id="IXT-4-1208"><primary>selectors,
  739: CSS</primary><secondary>pseudoclass</secondary></indexterm>feature of
  740: CSS-2 that Mozilla makes extensive use of is the
  741: <emphasis>pseudoclass</emphasis>. In CSS, pseudoclasses are used to
  742: represent different states for elements that are manipulated by the
  743: user, such as buttons. The states -- represented by pseudoclasses
  744: such as <literal>active</literal>, <literal>focus</literal>, and
  745: <literal>hover</literal> -- change when the user interacts with an
  746: element. The pseudoclasses actually correspond to events on the
  747: interface elements.
  748: </para>
  750: <para>The : character is used to add these <literal>pseudoclasses</literal>
  751: in the CSS notation:
  752: </para>
  754: <programlisting>#forwardButton:hover
  755: {
  756:   list-style-image      : url("chrome://navigator/skin/forward-hover.gif");
  757: }</programlisting>
  759: <para>The pseudoclass is often appended to another style. Since specific
  760: CSS style rules inherit from more general rules (see the section
  761: <link linkend="mozilla-CHP-4-SECT-3.1">Section 4.3.1</link> later in this chapter
  762: for more information about this inheritance), the example above picks
  763: up any styles defined for the button with the <literal>id</literal>
  764: of <literal>forwardButton</literal> (and any class-based information,
  765: as well as the basic CSS for a button), but substitutes whatever
  766: image is used with this special GIF that represents a button being
  767: moused or hovered over.
  768: </para>
  770: <para>In Mozilla's Modern skin, the pseudoclasses work
  771: collectively to give buttons their appearance and behavior. Each of
  772: the following button images in <link linkend="mozilla-CHP-4-FIG-3">Figure 4-3</link> is
  773: associated with a different pseudoclass (or attribute, as we discuss
  774: in the next section). As soon as the pseudoclass is changed by user
  775: interaction (e.g., the user hovers the mouse over the button), the
  776: state changes and the effect is one of seamless transition.
  777: </para>
  779: <figure id="mozilla-CHP-4-FIG-3" label="4-3">
  780: <title>The different states for buttons in the Modern theme</title>
  781: <graphic fileref="figs/moz_0403.png"/></figure>
  783: </sect3>
  785: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.7" label="">
  786: <title>Element relation selectors</title>
  788: <para>Contextual <indexterm id="IXT-4-1209"><primary>relational selectors,
  789: CSS</primary></indexterm><indexterm id="IXT-4-1210"><primary>CSS (Cascading Style
  790: Sheets)</primary><secondary>selectors</secondary><tertiary>relational</tertiary></indexterm><indexterm id="IXT-4-1211"><primary>selectors,
  791: CSS</primary><secondary>relational</secondary></indexterm>subgroups -- elements
  792: appearing within other elements, such as italicized text within a
  793: <literal>&lt;p&gt;</literal> element or a
  794: <literal>&lt;body&gt;</literal> in HTML -- can be grouped in CSS,
  795: but this is an extremely inefficient way to style XUL. CSS2 also
  796: provides ways to group elements for styling based on their
  797: relationship in the object model. <link linkend="mozilla-CHP-4-TABLE-1">Table 4-1</link> lists
  798: these relational selectors.
  799: </para>
  801: <table id="mozilla-CHP-4-TABLE-1" label="4-1">
  803: <title>Relational selectors </title>
  804: <tgroup cols="3">
  805: <colspec colnum="1" colname="col1"/>
  806: <colspec colnum="2" colname="col2"/>
  807: <colspec colnum="3" colname="col3"/>
  808: <thead>
  809: <row>
  810: <entry>
  811: <para>Selector</para>
  812: </entry>
  813: <entry>
  814: <para>Syntax</para>
  815: </entry>
  816: <entry>
  817: <para>Example</para>
  818: </entry>
  819: </row>
  820: </thead>
  821: <tbody>
  822: <row>
  823: <entry>
  824: <para>Descendent</para>
  825: </entry>
  826: <entry>
  827: <programlisting>ancestor descendent {
  828:  attribute: value;
  829: }</programlisting>
  830: </entry>
  831: <entry>
  832: <programlisting>toolbar.primary menutitem#F { 
  833:   border: 1px;
  834: }</programlisting>
  835: </entry>
  836: </row>
  837: <row>
  838: <entry>
  839: <para>Parent-Child</para>
  840: </entry>
  841: <entry>
  842: <programlisting>parent &gt; child {   
  843:   attribute: value;
  844: }</programlisting>
  845: </entry>
  846: <entry>
  847: <programlisting>menu#file &gt; menuitem {
  848:   font-weight: bold; 
  849: }</programlisting>
  850: </entry>
  851: </row>
  852: <row>
  853: <entry>
  854: <para>Precedence</para>
  855: </entry>
  856: <entry>
  857: <programlisting>elBefore + elAfter {
  858:   attribute: value;
  859: }</programlisting>
  860: </entry>
  861: <entry>
  862: <programlisting>menuitem#file + menuitem#edit {
  863:   background-color: black;
  864: }</programlisting>
  865: </entry>
  866: </row>
  867: </tbody>
  868: </tgroup>
  869: </table>
  871: <para>In the descendent example in <link linkend="mozilla-CHP-4-TABLE-1">Table 4-1</link>, the
  872: "F" <literal>menuitem</literal> has
  873: a border only when it appears within the <literal>toolbar</literal>
  874: whose class is given as "primary."
  875: In the parent-child example, all menu items in a menu with the
  876: <literal>id</literal> "file" are
  877: made bold. Using +, the precedence selector says that the
  878: "edit" menu should have a black
  879: background only when it comes after the
  880: "file" menu. You can use these
  881: element relation selectors to create longer descensions (e.g.,
  882: <literal>toolbar.primary &gt; menu#file &gt; menuitem#new</literal>),
  883: but remember that the processing gets more expensive with each new
  884: level, and that the descendent operation is particularly
  885: processor-intensive.
  886: </para>
  888: </sect3>
  890: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.8" label="">
  891: <title>The !important keyword</title>
  893: <para>As you might <indexterm id="IXT-4-1212"><primary>!important keyword
  894: (CSS)</primary></indexterm><indexterm id="IXT-4-1213"><primary>keywords,
  895: CSS</primary></indexterm><indexterm id="IXT-4-1214"><primary>CSS (Cascading Style
  896: Sheets)</primary><secondary>!important
  897: keyword</secondary></indexterm>imagine, when you have a technology
  898: with such strong notions of precedence as Cascading Style Sheets (the
  899: ID-based style trumps the class-based style, inline style attributes
  900: trump those loaded from an external stylesheet, etc.), you may need
  901: to identify and set aside certain styles as the most important,
  902: regardless of where they are found in the cascade.
  903: </para>
  905: <para>This is the role played by the <literal>!important</literal> keyword.
  906: Sitting to the right of a style value, it specifies that style rule
  907: should take precedence over all of its competitors and that it should
  908: be applied all the time. <link linkend="mozilla-CHP-4-EX-3">Example 4-3</link> demonstrates
  909: how no borders are rendered on <filename>treecells </filename>of the
  910: class <filename>treecell-editor</filename> because of the
  911: <literal>!important</literal> keyword.
  912: </para>
  914: <example id="mozilla-CHP-4-EX-3" label="4-3">
  915: <title>!important keyword in CSS </title>
  916: <programlisting>.treecell-editor,
  917: .treecell-editor &gt; box {
  918:   margin: 0px !important;
  919:   padding: 0px !important;
  920: }
  921: .treecell-editor {
  922:   border: 0px !important;
  923: }</programlisting>
  924: </example>
  926: <para>You can search for the <literal>!important</literal> keyword in the
  927: LXR Mozilla source code tool and see its use in the Mozilla CSS.
  928: </para>
  930: </sect3>
  932: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.9" label="">
  933: <title>The inherits value</title>
  935: <para>CSS uses <indexterm id="IXT-4-1215"><primary>inherits value
  936: (CSS)</primary></indexterm><indexterm id="IXT-4-1216"><primary>CSS (Cascading Style
  937: Sheets)</primary><secondary>inherits
  938: value</secondary></indexterm>inheritance all over the place.
  939: Inheritance is implicit in the way style rules are applied,
  940: stylesheets are organized in the chrome, and skins borrow from one
  941: another in Mozilla. However, a special CSS value indicates that the
  942: selector explicitly inherits its value from the parent element.
  943: </para>
  945: <para>When a CSS property has a value of <literal>inherit</literal>, that
  946: property's real value is pulled from the parent
  947: element:
  948: </para>
  950: <programlisting>.child {
  951:   color: darkblue;
  952:   height: <userinput>inherit</userinput>;
  953:   background-color: <userinput>inherit</userinput>;
  954: }</programlisting>
  956: <para>This block specifies a dark blue color for the font, but the values
  957: of the other two properties are inherited from the parent. In many
  958: cases, this has the same effect as not specifying any value at all
  959: for the child and letting the style rules above the current one in
  960: the document inheritance chain cascade down. However, not all style
  961: rules are inherited. Properties such as
  962: <literal>!important</literal>, <literal>left</literal>, and
  963: <literal>height</literal> are not inherited automatically by child
  964: elements, so you must use the <literal>inherit</literal> keyword to
  965: pick them up.
  966: </para>
  968: </sect3>
  970: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.10" label="">
  971: <title>Box layout properties in CSS</title>
  973: <para>People sometimes
  974: <indexterm id="IXT-4-1217"><primary>properties</primary><secondary>CSS</secondary><tertiary>box
  975: layout</tertiary></indexterm><indexterm id="IXT-4-1218"><primary>layout, CSS box
  976: layout properties</primary></indexterm><indexterm id="IXT-4-1219"><primary>box layout
  977: properties (CSS)</primary></indexterm><indexterm id="IXT-4-1220"><primary>CSS
  978: (Cascading Style Sheets)</primary><secondary>properties, box
  979: layout</secondary></indexterm>get confused about the various element
  980: spacing properties in CSS, such as <literal>border</literal>,
  981: <literal>padding</literal>, and <literal>margin</literal>. Though
  982: they work together a lot and often affect or overlap one another,
  983: these properties specify different things, as <link linkend="mozilla-CHP-4-TABLE-2">Table 4-2</link> shows.
  984: </para>
  986: <table id="mozilla-CHP-4-TABLE-2" label="4-2">
  988: <title>CSS spacing and layout properties </title>
  989: <tgroup cols="3">
  990: <colspec colnum="1" colname="col1"/>
  991: <colspec colnum="2" colname="col2"/>
  992: <colspec colnum="3" colname="col3"/>
  993: <thead>
  994: <row>
  995: <entry>
  996: <para>Property group</para>
  997: </entry>
  998: <entry>
  999: <para>Description</para>
 1000: </entry>
 1001: <entry>
 1002: <para>Display</para>
 1003: </entry>
 1004: </row>
 1005: </thead>
 1006: <tbody>
 1007: <row>
 1008: <entry>
 1009: <programlisting>padding</programlisting>
 1010: </entry>
 1011: <entry>
 1012: <para>Defines the space between the element's border and
 1013: the content in the element.
 1014: </para>
 1016: <programlisting>td {padding-left: .25in;}
 1017: td {padding-left: .0125in;}</programlisting>
 1018: </entry>
 1019: <entry>
 1022: <para><graphic fileref="figs/ch04-6.png"/></para>
 1023: </entry>
 1024: </row>
 1025: <row>
 1026: <entry>
 1027: <programlisting>margin</programlisting>
 1028: </entry>
 1029: <entry>
 1030: <para>Defines the space around elements.</para>
 1032: <programlisting>td {margin-left: .25in;}</programlisting>
 1033: </entry>
 1034: <entry>
 1037: <para><graphic fileref="figs/ch04-7.png"/></para>
 1038: </entry>
 1039: </row>
 1040: <row>
 1041: <entry>
 1042: <programlisting>border</programlisting>
 1043: </entry>
 1044: <entry>
 1045: <para>Defines the border itself; it can control the thickness, color,
 1046: style, and other aspects of an element's border.
 1047: </para>
 1049: <programlisting>td {border-style: inset;}
 1050: td {border-color: blue;}
 1051: td {border-left-width: 15px;}</programlisting>
 1052: </entry>
 1053: <entry>
 1056: <para><graphic fileref="figs/ch04-8.png"/></para>
 1057: </entry>
 1058: </row>
 1059: </tbody>
 1060: </tgroup>
 1061: </table>
 1063: </sect3>
 1065: <sect3 role="" id="mozilla-CHP-4-SECT-2.2.11" label="">
 1066: <title>The position property</title>
 1068: <para><literal>position</literal> is a <indexterm id="IXT-4-1221"><primary>position
 1069: property
 1070: (CSS)</primary></indexterm><indexterm id="IXT-4-1222"><primary>properties</primary><secondary>CSS</secondary><tertiary>position</tertiary></indexterm><indexterm id="IXT-4-1223"><primary>CSS
 1071: (Cascading Style Sheets)</primary><secondary>position
 1072: property</secondary></indexterm>special CSS property
 1073: <indexterm id="IXT-4-1224"><primary>alignment, CSS position
 1074: property</primary></indexterm>that specifies whether the given
 1075: selector uses absolute or relative positioning. Unless you set the
 1076: <literal>position</literal> property to absolute, you cannot use the
 1077: related <literal>top</literal> and <literal>left</literal> properties
 1078: to set the position of the current selector within its parent, as the
 1079: example in <link linkend="mozilla-CHP-4-TABLE-3">Table 4-3</link> demonstrates. The
 1080: <literal>top</literal> and <literal>left</literal> properties, when
 1081: activated by the absolute position, specify the amount of distance
 1082: from the top and left of the document, respectively. You can also set
 1083: <literal>position</literal> to <literal>fixed</literal> to make it
 1084: stay in one place as other content or UI is scrolled or<indexterm id="IXTR3-1297" class="endofrange" startref="mozilla-IDXTERM-530"/><indexterm id="IXTR3-1298" class="endofrange" startref="mozilla-IDXTERM-531"/> moved.
 1085: </para>
 1087: <table id="mozilla-CHP-4-TABLE-3" label="4-3">
 1089: <title>The position property </title>
 1090: <tgroup cols="2">
 1091: <colspec colnum="1" colname="col1"/>
 1092: <colspec colnum="2" colname="col2"/>
 1093: <thead>
 1094: <row>
 1095: <entry>
 1096: <para>Example</para>
 1097: </entry>
 1098: <entry>
 1099: <para>Display</para>
 1100: </entry>
 1101: </row>
 1102: </thead>
 1103: <tbody>
 1104: <row>
 1105: <entry>
 1106: <programlisting>&lt;style&gt;
 1107: #abdiv {
 1108:  position: absolute;
 1109:  top: 20px;
 1110:  left: 70px;
 1111:  background-color: lightblue;
 1112: }
 1113: #regdiv {
 1114:  background-color: lightblue;
 1115: }
 1116: &lt;/style&gt;
 1117: &lt;div id="regdiv"&gt;other div&lt;/div&gt;
 1118: &lt;div id="abdiv"&gt;abdiv&lt;/div&gt;</programlisting>
 1119: </entry>
 1120: <entry>
 1123: <para><graphic fileref="figs/ch04-9.png"/></para>
 1124: </entry>
 1125: </row>
 1126: </tbody>
 1127: </tgroup>
 1128: </table>
 1130: </sect3>
 1131: </sect2>
 1132: <sect2 role="" id="mozilla-CHP-4-SECT-2.3" label="4.2.3">
 1133: <title>Special Mozilla Extensions</title>
 1135: <para>Mozilla skins <indexterm id="IXT-4-1225"><primary>selectors,
 1136: CSS</primary><secondary>extensions</secondary></indexterm><indexterm id="IXT-4-1226"><primary>Mozilla</primary><secondary>CSS
 1137: extensions</secondary></indexterm><indexterm id="IXT-4-1227"><primary>CSS (Cascading
 1138: Style
 1139: Sheets)</primary><secondary>extensions</secondary></indexterm><indexterm id="IXT-4-1228"><primary>properties</primary><secondary>CSS</secondary><tertiary>Mozilla
 1140: extensions</tertiary></indexterm><indexterm id="IXT-4-1229"><primary>extensions, CSS
 1141: selectors and properties</primary></indexterm>extend
 1142: <indexterm id="IXT-4-1230"><primary>skins</primary><secondary>Mozilla CSS
 1143: extensions</secondary></indexterm>upon the CSS standards in just a
 1144: few notable ways. These Mozilla CSS extensions take the form of
 1145: special selectors and properties with the special
 1146: <literal>-moz-</literal> prefix, indicating that they are not part of
 1147: the actual CSS specifications. You can find a complete list of these
 1148: CSS keywords by searching for the file
 1149: <filename>nsCSSKeyWordList.h</filename> in LXR.
 1150: </para>
 1152: <para>Generally, these extensions are used to define CSS style and color
 1153: values that are hardcoded into the C++ code and available for reuse
 1154: in particular places in the Mozilla themes. You can use a few
 1155: <filename>-moz-</filename> extensions, such as properties or special
 1156: values or even, in some cases, style-related attributes in the XUL
 1157: (e.g., <literal>span[-moz-smiley="s1"]</literal>, which grabs span
 1158: elements in the HTML editor whose -<literal>moz-smiley</literal>
 1159: attribute is set to <literal>s1</literal> and styles them
 1160: accordingly). Actually, you can use any value in that CSS keyword
 1161: list. Trial and error or a look in the C++ code will reveal what
 1162: these values are. The values, like <literal>-moz-fieldtext</literal>
 1163: and <literal>-moz-mac-menushadow</literal>, usually refer to actual
 1164: color values. A list of some Mozilla CSS extensions appears in <link linkend="mozilla-CHP-4-TABLE-4">Table 4-4</link>. 
 1165: </para>
 1167: <table id="mozilla-CHP-4-TABLE-4" label="4-4">
 1169: <title>Mozilla CSS extensions </title>
 1170: <tgroup cols="2">
 1171: <colspec colnum="1" colname="col1"/>
 1172: <colspec colnum="2" colname="col2"/>
 1173: <thead>
 1174: <row>
 1175: <entry>
 1176: <para>Property</para>
 1177: </entry>
 1178: <entry>
 1179: <para>Description</para>
 1180: </entry>
 1181: </row>
 1182: </thead>
 1183: <tbody>
 1184: <row>
 1185: <entry>
 1186: <programlisting>-moz-appearance</programlisting>
 1187: </entry>
 1188: <entry>
 1189: <para>Specifies that the element should appear, as much as possible, as an
 1190: operating-system native.
 1191: </para>
 1192: </entry>
 1193: </row>
 1194: <row>
 1195: <entry>
 1196: <programlisting>-moz-opacity</programlisting>
 1197: </entry>
 1198: <entry>
 1199: <para>Controls the opacity of any styleable element with a percentage
 1200: value. The following example style rule creates a class of buttons
 1201: that are only half visible above their backgrounds:
 1202: </para>
 1204: <programlisting>.op-butt {
 1205:   -moz-opacity: 50%;
 1206: }</programlisting>
 1207: </entry>
 1208: </row>
 1209: <row>
 1210: <entry>
 1211: <programlisting>-moz-binding</programlisting>
 1212: </entry>
 1213: <entry>
 1214: <para>The property for binding XBL to XUL. The value of
 1215: <literal>-moz-binding</literal> is a URL pointing to the section in
 1216: an XML bindings file where the XBL is defined:
 1217: </para>
 1219: <programlisting>new-widget {
 1220:   -moz-binding: 
 1221:      chrome://xfly/bindings/extras.xml#super-button;
 1222: }</programlisting>
 1223: </entry>
 1224: </row>
 1225: <row>
 1226: <entry>
 1227: <programlisting>-moz-border-radius,
 1228: -moz-border-radius-bottomleft,
 1229: -moz-border-radius-bottomright,
 1230: -moz-border-radius-topleft,
 1231: -moz-border-radius-topright</programlisting>
 1232: </entry>
 1233: <entry>
 1234: <para>Puts rounded corners on regular borders. The degree of rounding
 1235: depends on the number of pixels you assign. For example, if you set
 1236: this property to <literal>2px</literal>, you get a slightly rounded
 1237: border, but if you set it to <literal>8px</literal>, you get a very
 1238: round border.
 1239: </para>
 1240: </entry>
 1241: </row>
 1242: <row>
 1243: <entry>
 1244: <programlisting>-moz-border-colors,
 1245: -moz-border-colors-bottom,
 1246: -moz-border-colors-left,
 1247: -moz-border-colors-right,
 1248: -moz-border-colors-top</programlisting>
 1249: </entry>
 1250: <entry>
 1251: <para>Sets the border colors on the various sides of an element.</para>
 1252: </entry>
 1253: </row>
 1254: <row>
 1255: <entry>
 1256: <programlisting>-moz-user-focus</programlisting>
 1257: </entry>
 1258: <entry>
 1259: <para>Indicates whether the given element can have focus. Possible values
 1260: are <literal>normal</literal> and <literal>ignore</literal>.
 1261: </para>
 1262: </entry>
 1263: </row>
 1264: <row>
 1265: <entry>
 1266: <programlisting>-moz-user-select</programlisting>
 1267: </entry>
 1268: <entry>
 1269: <para>Indicates whether the given element can be selected. Possible values
 1270: are <literal>none</literal> and <literal>normal</literal>.
 1271: </para>
 1272: </entry>
 1273: </row>
 1274: <row>
 1275: <entry>
 1276: <programlisting>-moz-smiley</programlisting>
 1277: </entry>
 1278: <entry>
 1279: <para>This is typically given as an attribute to the span element in the
 1280: HTML in a composer window and can be set to a value such as
 1281: <literal>s5</literal> to pick up the laughing smiley image, to
 1282: <literal>s6</literal> to pick up the embarrassed smiley image, and so
 1283: on.
 1284: </para>
 1286: <para>See the following source file for the values that can be set for this
 1287: special property: <systemitem role="url"></systemitem>.
 1288: </para>
 1289: </entry>
 1290: </row>
 1291: <row>
 1292: <entry>
 1293: <programlisting>-moz-image-region</programlisting>
 1294: </entry>
 1295: <entry>
 1296: <para>This was added to optimize the way image resources are used in the
 1297: Mozilla skins. The value of the <literal>-moz-image</literal> region
 1298: is a set of coordinates that designate an area within an
 1299: "image sheet" that should be used
 1300: as an icon in the user interface. The following CSS style definition
 1301: specifies the top- and leftmost button in the
 1302: <filename>btn1.gif</filename> image sheet used in <link linkend="mozilla-CHP-4-FIG-3">Figure 4-3</link> to use as the default icon for the Back
 1303: navigation button:
 1304: </para>
 1306: <programlisting>.toolbarbutton-1 {
 1307:  list-style-image: url("chrome://navigator/skin/icons/btn1.gif");
 1308:  min-width: 0px;
 1309: }
 1310: #back-button {
 1311:  -moz-image-region: rect(0 41px 38px 0);
 1312: }</programlisting>
 1314: <para>Of the two default skins, these image sheets are found only in the
 1315: Modern skin. They are gradually making their way into the skins; as
 1316: of this writing, there are three or four image sheets in the Modern
 1317: skin -- each corresponding to an area, toolbar, or set of buttons
 1318: in the browser.
 1319: </para>
 1320: </entry>
 1321: </row>
 1322: <row>
 1323: <entry>
 1324: <programlisting>-moz-box-align</programlisting>
 1325: </entry>
 1326: <entry>
 1327: <para>Sets the alignment for a XUL element from CSS. Possible values are
 1328: <literal>start</literal>, <literal>center</literal>,
 1329: <literal>end</literal>, <literal>baseline</literal>, and
 1330: <literal>stretch</literal>.
 1331: </para>
 1332: </entry>
 1333: </row>
 1334: <row>
 1335: <entry>
 1336: <programlisting>-moz-box-direction</programlisting>
 1337: </entry>
 1338: <entry>
 1339: <para>Sets the direction of a box's child elements.
 1340: Possible values are <literal>normal</literal> and
 1341: <literal>reverse</literal>.
 1342: </para>
 1343: </entry>
 1344: </row>
 1345: <row>
 1346: <entry>
 1347: <programlisting>-moz-box-flex</programlisting>
 1348: </entry>
 1349: <entry>
 1350: <para>Sets the flexibility of an element relative to its siblings. The
 1351: value is an integer.
 1352: </para>
 1353: </entry>
 1354: </row>
 1355: <row>
 1356: <entry>
 1357: <programlisting>-moz-box-flexgroup</programlisting>
 1358: </entry>
 1359: <entry>
 1360: <para>Specifies that a group of elements have the same flex. The value is
 1361: an integer.
 1362: </para>
 1363: </entry>
 1364: </row>
 1365: <row>
 1366: <entry>
 1367: <programlisting>-moz-box-ordinal</programlisting>
 1368: </entry>
 1369: <entry>
 1370: <para>Specifies the order of an element relative to its peers in a
 1371: container. By default, the value of this property is set to 1. When
 1372: you set a new value, you can change the order, as in this example,
 1373: which promotes the "View Source"
 1374: menu item to the top of the menu by demoting the other two:
 1375: </para>
 1377: <programlisting>&lt;style&gt;
 1378: #q { -moz-box-ordinal: 0; }
 1379: &lt;/style&gt;
 1380: &lt;menu&gt;
 1381:   &lt;menuitem id="e" label="e" /&gt;
 1382:   &lt;menuitem id="v" label="v" /&gt;
 1383:   &lt;menuitem id="q" label="q" /&gt;
 1384: &lt;/menu&gt;
 1385: &lt;/window&gt;</programlisting>
 1387: <para>You can also give elements the same ordinal value in CSS and group
 1388: them, making sure they are not split by new, overlaid items.
 1389: </para>
 1390: </entry>
 1391: </row>
 1392: <row>
 1393: <entry>
 1394: <programlisting>-moz-box-orient</programlisting>
 1395: </entry>
 1396: <entry>
 1397: <para>Sets the orientation of a container element. The value can be either
 1398: <literal>horizontal</literal> or <literal>vertical</literal>.
 1399: </para>
 1400: </entry>
 1401: </row>
 1402: <row>
 1403: <entry>
 1404: <programlisting>-moz-box-pack</programlisting>
 1405: </entry>
 1406: <entry>
 1407: <para>Packs the child elements of a container at the
 1408: <literal>start</literal>, <literal>center</literal>, or
 1409: <literal>end</literal>.
 1410: </para>
 1411: </entry>
 1412: </row>
 1413: </tbody>
 1414: </tgroup>
 1415: </table>
 1417: </sect2>
 1418: <sect2 role="" id="mozilla-CHP-4-SECT-2.4" label="4.2.4">
 1419: <title>Referencing Images in CSS</title>
 1421: <para>Another basic <indexterm id="IXT-4-1231"><primary>skins</primary><secondary>images,
 1422: referencing</secondary></indexterm><indexterm id="IXT-4-1232"><primary>images</primary><secondary>skins,
 1423: referencing</secondary></indexterm><indexterm id="IXT-4-1233"><primary>CSS (Cascading
 1424: Style Sheets)</primary><secondary>images,
 1425: referencing</secondary></indexterm><indexterm id="IXT-4-1234"><primary>referencing</primary><secondary>images,
 1426: CSS</secondary></indexterm>function of the CSS in any Mozilla skin is
 1427: to incorporate images into the user interface. A Mozilla skin can
 1428: contain literally thousands of images, which are all referenced from
 1429: particular style statements in the CSS. It's common
 1430: for a single element to point to different versions of an image to
 1431: reflect different states -- as when a second image is used to give
 1432: a button a pushed-down look as it is clicked -- to create dynamism
 1433: and provide feedback to the user. <link linkend="mozilla-CHP-4-EX-4">Example 4-4</link> shows
 1434: the following two style statements handle the regular and
 1435: active -- or depressed -- states, respectively.
 1436: </para>
 1438: <example id="mozilla-CHP-4-EX-4" label="4-4">
 1439: <title>Image in CSS </title>
 1440: <programlisting>button.regular {
 1441:     list-style-image: url(chrome://global/skin/arrow.gif);
 1442:     background-image: url(chrome://global/skin/regbutton.gif);
 1443: } 
 1444: button.regular:active 
 1445: {
 1446:     background-image: url(chrome://global/skin/button_pushed.gif); 
 1447: }</programlisting>
 1448: </example>
 1450: <para>In <link linkend="mozilla-CHP-4-EX-4">Example 4-4</link>, the second of the two definitions
 1451: inherits from the first, so it implicitly includes the
 1452: <filename>arrow.gif</filename> as a foreground image. The second
 1453: style definition says that when the XUL button of class
 1454: <literal>regular</literal> is active, the image
 1455: <filename>button_pushed.gif</filename> is used in place of
 1456: <filename>regbutton.gif</filename> for the background.
 1457: </para>
 1459: <para><link linkend="mozilla-CHP-4-EX-4">Example 4-4</link> also
 1460: illustrates<indexterm id="IXT-4-1235"><primary>properties</primary><secondary>CSS</secondary><tertiary>referencing
 1461: images</tertiary></indexterm> the two common stylesheet properties
 1462: that reference images: <literal>list-style-image</literal> and
 1463: <literal>background-image</literal>. The
 1464: <literal>list-style-image</literal><indexterm id="IXT-4-1236"><primary>list-style-image
 1465: property (CSS)</primary></indexterm> property specifies an image to
 1466: go in the foreground of the selector; the
 1467: <literal>background-image</literal> property specifies a separate
 1468: image for the background. The availability of these two properties
 1469: allows you to fine-tuning the images used to style the UI, as in this
 1470: example, where the arrow icon is preserved and the wider, underlying
 1471: button is swapped out.
 1472: </para>
 1474: <para>In fact, the navigation buttons in the Modern skin are created by
 1475: using both properties. In this case, the background is the basic
 1476: round disk as seen in <link linkend="mozilla-CHP-4-FIG-4">Figure 4-4</link>, defined in the
 1477: <literal>toolbarbutton-1</literal> class in
 1478: <filename>communicator\skin\button.css</filename>, and the
 1479: <literal>list-style-image</literal> is the arrow portion of the
 1480: button, defined in the button ID and sliced out of a button image
 1481: sheet with the special <literal>-moz-image-region</literal> property
 1482: (see <link linkend="mozilla-CHP-4-SECT-2.3">Section 4.2.3</link> later in this
 1483: chapter for a description of image sheets).
 1484: </para>
 1486: <figure id="mozilla-CHP-4-FIG-4" label="4-4">
 1487: <title>Composite styles for the reload button</title>
 1488: <graphic fileref="figs/moz_0404.png"/></figure>
 1490: </sect2>
 1491: <sect2 role="" id="mozilla-CHP-4-SECT-2.5" label="4.2.5">
 1492: <title>Menu Skinning</title>
 1494: <para>As an example <indexterm id="IXT-4-1237"><primary>menus</primary><secondary>CSS,
 1495: skinning</secondary></indexterm><indexterm id="IXT-4-1238"><primary>skins</primary><secondary>menus</secondary></indexterm><indexterm id="IXT-4-1239"><primary>CSS
 1496: (Cascading Style Sheets)</primary><secondary>menus,
 1497: skins</secondary></indexterm>of using CSS in applications, <link linkend="mozilla-CHP-4-EX-5">Example 4-5</link> combines many common selectors described in
 1498: this chapter in a set of rules for defining the look and basic
 1499: behavior of menus. The CSS handles the basic look of the menus, their
 1500: color and style, the look of the menu items when they are hovered
 1501: over, and the look when they are selected.
 1502: </para>
 1504: <example id="mozilla-CHP-4-EX-5" label="4-5">
 1505: <title>Mixing CSS and XUL </title>
 1506: <programlisting>&lt;menu id="sample"&gt;
 1507:   &lt;menupopup&gt;
 1508:     &lt;menuitem class="m" label="File" /&gt;
 1509:     &lt;menuitem class="m" label="Edit" /&gt;
 1510:     &lt;menuitem class="m" id="q" label="Quit" /&gt;
 1511:   &lt;/menupopup&gt;
 1512: &lt;/menu&gt;
 1513: .m { background-color: lightgray; font-size: 9pt; }
 1514: .m:hover  { border: 1px; }
 1515: .m:active { background-color: gray; color: white; }
 1516: #q:active { background-color: black }</programlisting>
 1517: </example>
 1519: <para>When you hover over any of the items in the menu generated by the
 1520: code in <link linkend="mozilla-CHP-4-EX-5">Example 4-5</link>, they display a border. When you
 1521: select the item, it appears momentarily with a dark gray background
 1522: and white lettering, like reverse video. The Quit menu item, unlike
 1523: others, appears with a black background. Note that it also picks up
 1524: the same white lettering as the other items of the
 1525: <literal>m</literal> class, since this style information is
 1526: inherited.
 1527: </para>
 1529: </sect2>
 1530: </sect1>
 1532: <sect1 role="" id="mozilla-CHP-4-SECT-3" label="4.3">
 1533: <title>Mozilla Skins</title>
 1535: <para>At an earlier <indexterm id="IXT-4-1240"><primary>chrome</primary><secondary>skins,
 1536: file
 1537: locations</secondary></indexterm><indexterm id="IXT-4-1241"><primary>skins</primary><secondary>file
 1538: locations</secondary></indexterm><indexterm id="IXT-4-1242"><primary>files</primary><secondary>skins,
 1539: locations</secondary></indexterm>point in Mozilla's
 1540: history, all interface files -- the XUL, the CSS, and the
 1541: images -- were stored in directories named after the main Mozilla
 1542: packages in the application chrome directory. The best way to look at
 1543: a skin was just to poke around in those directories, change things in
 1544: the CSS files you found, and reload to see what had changed in the
 1545: browser. The CSS files are no longer stored in regular directories.
 1546: </para>
 1548: <para>To organize things better and make a smaller footprint for Mozilla,
 1549: all chrome is stored in special compressed archives in the
 1550: <filename>chrome</filename> directory. These archives are Java
 1551: Archive (JAR) files, whose subdirectory structure reflects the
 1552: structure of Mozilla's major components, to some
 1553: extent. There is one JAR archive for every theme. By default, Mozilla
 1554: is distributed with the Classic and Modern themes, represented in the
 1555: chrome as <literal>classic.jar</literal> and
 1556: <literal>modern.jar</literal>. <link linkend="mozilla-CHP-4-FIG-5">Figure 4-5</link> shows
 1557: some of the contents of the <literal>modern.jar</literal> file in a
 1558: zip utility.
 1559: </para>
 1561: <figure id="mozilla-CHP-4-FIG-5" label="4-5">
 1562: <title>The contents of the modern.jar file</title>
 1563: <graphic fileref="figs/moz_0405.png"/></figure>
 1565: <sect2 role="" id="mozilla-CHP-4-SECT-3.1" label="4.3.1">
 1566: <title>CSS and Skin Hierarchies</title>
 1568: <para>You have <indexterm id="IXT-4-1243"><primary>CSS (Cascading Style
 1569: Sheets)</primary><secondary>skins</secondary><tertiary>hierarchy</tertiary></indexterm><indexterm id="IXT-4-1244"><primary>skins</primary><secondary>hierarchy</secondary></indexterm><indexterm id="IXT-4-1245"><primary>hierarchy</primary><secondary>skins</secondary></indexterm><indexterm id="IXT-4-1246"><primary>inheritance</primary><secondary>skin
 1570: hierarchies</secondary></indexterm>already seen some of the structure
 1571: inherent to CSS in the previous examples. When an element has both a
 1572: class-based and an id-based rule, for example (as well as a basic
 1573: element "look and feel" defined in
 1574: the global skin), the element style is applied. Then, the more
 1575: specific class-based rule is applied and overwrites the properties of
 1576: the general rule if they conflict. Finally, the ID-based rule is
 1577: applied and overwrites whatever conflicting style values are in the
 1578: more general selectors. In this way, the most specific style rules
 1579: inherit from the most basic. This is the
 1580: "cascade" in Cascading Style
 1581: Sheets. In addition to this definition, the syntax of CSS allows you
 1582: to specify selector relationships -- such as when you create a
 1583: parent-child selector and apply a style rule to only the selectors
 1584: that have some other particular element as a parent in the XUL
 1585: content model. However, there is also a strong inheritance mechanism
 1586: in the way that the Mozilla browser uses CSS -- in the way skin
 1587: files are organized in the chrome and applied to the XUL. The strong
 1588: hierarchical structure present in Mozilla's CSS and
 1589: the XUL allow the chrome registry to maintain the skin and the
 1590: various components that get skinned as different modules, but find
 1591: and apply the right resources whenever they are called for. This
 1592: structure is described in the <link linkend="mozilla-CHP-4-SECT-3.2">Section 4.3.2</link> section later in this
 1593: chapter.
 1594: </para>
 1596: <sect3 role="" id="mozilla-CHP-4-SECT-3.1.1" label="">
 1597: <title>Skin inheritance and skin modularization</title>
 1599: <para>For the sake of
 1600: <indexterm id="IXT-4-1247"><primary>skins</primary><secondary>inheritance</secondary></indexterm><indexterm id="IXT-4-1248"><primary>skins</primary><secondary>modularization</secondary></indexterm><indexterm id="IXT-4-1249"><primary>modularization,
 1601: skins</primary></indexterm>discussion, this book describes two kinds
 1602: of inheritance: the more basic form, in which a specific skin like
 1603: <filename>navigator.css</filename> inherits all style rules from
 1604: <filename>global.css</filename>, and modularization, in which
 1605: navigator skin rules specific to the toolbar are distributed into
 1606: widget-specific CSS files (e.g., <filename>toolbar.css</filename> is
 1607: part of the global skin). The global skin -- once a large,
 1608: unmodular set of style rules contained in
 1609: <filename>global.css</filename> -- is now spread out over several
 1610: modularized CSS files, as <link linkend="mozilla-CHP-4-FIG-6">Figure 4-6</link> shows.
 1611: </para>
 1613: <figure id="mozilla-CHP-4-FIG-6" label="4-6">
 1614: <title>XUL file and skin loading</title>
 1615: <graphic fileref="figs/moz_0406.png"/></figure>
 1617: <para>This modularization makes it possible for a <indexterm id="IXT-4-1250"><primary>XUL
 1618: (XML-based User-interface Language)</primary><secondary>skin
 1619: modularization</secondary></indexterm>XUL file to load the
 1620: <filename>global.css</filename> file in a single statement and use
 1621: any of the style rules defined in these skins. We will discuss the
 1622: global skin in more detail in the section <link linkend="mozilla-CHP-4-SECT-3.4.2">Section</link> later in this chapter. Skin
 1623: inheritance and skin modularization work together to give skins their
 1624: structure and make it possible to create new skins or apply CSS only
 1625: to particular parts of the application.
 1626: </para>
 1628: <para><link linkend="mozilla-CHP-4-FIG-6">Figure 4-6</link> shows a very specific skin,
 1629: <filename>new.css</filename>, inheriting the style information from
 1630: <filename>communicator.css</filename> and then being loaded into the
 1631: XUL file. In a situation like this, <filename>ex.xul</filename> can
 1632: use any style rule defined in the
 1633: <filename>communicator.css</filename> file (or in any CSS file that
 1634: it imports).
 1635: </para>
 1637: </sect3>
 1638: </sect2>
 1639: <sect2 role="" id="mozilla-CHP-4-SECT-3.2" label="4.3.2">
 1640: <title>Basic Skin Structure</title>
 1642: <para>Though they
 1643: look<indexterm id="IXT-4-1251"><primary>themes</primary><secondary>structure</secondary></indexterm><indexterm id="IXT-4-1252"><primary>skins</primary><secondary>structure</secondary></indexterm>
 1644: very different, the Modern and Classic themes that are installed with
 1645: Mozilla have similar structures. This is because the structure of a
 1646: theme reflects, in many ways, the structure of the components to
 1647: which it applies. So, for example, both themes have subdirectories
 1648: (in the JAR files in which they are stored) where the CSS and image
 1649: resources for each of the main components are stored. Modern, for
 1650: example, has a <filename>communicator</filename> component
 1651: subdirectory, and that subdirectory has subdirectories representing
 1652: the various parts of the communicator interface: bookmarks, help,
 1653: search, sidebar, and so on. <link linkend="mozilla-CHP-4-EX-7">Example 4-7</link> shows the
 1654: Modern and Classically themed Navigation bars side by side.
 1655: </para>
 1657: <figure id="mozilla-CHP-4-FIG-7" label="4-7">
 1658: <title>Classic and Modern Navigation toolbars</title>
 1659: <graphic fileref="figs/moz_0407.png"/></figure>
 1661: <para>Both themes are complete. They each contain all skin resources for
 1662: the major components of the application.<footnote label="1"> <para>There are
 1663: just a couple of exceptions to this rule. The
 1664: <filename>content</filename> directory of a package (typically the
 1665: place where just the XUL and JS are stored) sometimes holds a file
 1666: called <filename>xul.css</filename>. This file defines style
 1667: information that is so fundamental to the way widgets are
 1668: rendered -- more fundamental, even, then
 1669: <filename>global.css</filename> and its siblings -- that it is set
 1670: apart from the regular skin and put in with the content, where it is
 1671: loaded automatically. It's not a good idea to edit
 1672: this file.</para> </footnote> The resources themselves vary, but
 1673: their structures are almost identical. This ability is what makes the
 1674: skins dynamically changeable.
 1675: </para>
 1677: <para>Skin developers can, for example, create a skin for a single
 1678: component in Mozilla (e.g., messenger) and let the Modern theme
 1679: continue to take care of the other components for which they have not
 1680: created any new CSS information. Which components are skinned by
 1681: which themes is specified in the
 1682: <filename>installed-chrome.txt</filename> file, where a single entry
 1683: represents the application of the appropriate theme resources to a
 1684: single component, such as navigator. (See <link linkend="mozilla-CHP-6">Chapter 6</link> for more information about this file and about
 1685: how themes and other packages are registered and applied in Mozilla.)
 1686: This situation does not apply to new applications like xFly, however,
 1687: for which the XUL is typically a single package and the CSS that
 1688: applies to it is another single package. Unlike the Mozilla browser,
 1689: your application will probably have a single manifest and
 1690: <filename>content</filename> subdirectory and a single manifest and
 1691: <filename>skin</filename> subdirectory:
 1692: </para>
 1694: <programlisting>xfly.jar:
 1695:     content/
 1696:         contents.rdf
 1697:         &lt;xul content here&gt;
 1698:     skin/
 1699:         contents.rdf
 1700:         &lt;css content here&gt;</programlisting>
 1702: <para>An important difference here is that your skin requires a single
 1703: manifest whereas the Mozilla themes use as many manifests as they
 1704: have major components to skin. When the application that needs to be
 1705: skinned is as large as the Mozilla browser, modularity is almost
 1706: imperative -- particularly if that application supports add-on
 1707: applications (like xFly itself, which will be accessible from the
 1708: Mozilla Tasks menu when you are done).
 1709: </para>
 1711: </sect2>
 1712: <sect2 role="" id="mozilla-CHP-4-SECT-3.3" label="4.3.3">
 1713: <title>The Modern and Classic Themes</title>
 1715: <para>If you
 1716: haven't<indexterm id="IXT-4-1253"><primary>skins</primary><secondary>Modern
 1717: compared to Classic</secondary></indexterm><indexterm id="IXT-4-1254"><primary>Modern
 1718: theme</primary><secondary>compared to
 1719: Classic</secondary></indexterm><indexterm id="IXT-4-1255"><primary>Classic theme
 1720: compared to
 1721: Modern</primary></indexterm><indexterm id="IXT-4-1256"><primary>themes</primary><secondary>Modern</secondary><tertiary>compared
 1722: to Classic</tertiary></indexterm> already looked at it, using the
 1723: skin-switching UI (View Menu &gt; Apply Theme
 1724: &gt; Modern) in Mozilla will give you an idea about the
 1725: differences between the two skins that come preinstalled with the
 1726: browser. The Classic skin is modeled after earlier versions of the
 1727: Mozilla UI and of the Netscape 4.x Communicator product. It has the
 1728: familiar light grey box look, with the larger, primary-colored
 1729: navigation button and a squared-off geometry. The Modern theme is a
 1730: newer take on the browser interface. It has a smoother overall look,
 1731: with rounded edges on many of the widgets, subtle color
 1732: differentiations, gradients, and 3D icons.
 1733: </para>
 1735: <para>However, both skins sit on top of the same XUL. With one notable
 1736: exception -- a powerful feature of CSS in Mozilla discussed later
 1737: in this chapter in the <link linkend="mozilla-CHP-4-SECT-5.1">Section 4.5.1</link>
 1738: section -- the applications themselves are identical, and themes
 1739: themselves provide all the differences in the
 1740: browser's look and behavior.
 1741: </para>
 1743: </sect2>
 1744: <sect2 role="" id="mozilla-CHP-4-SECT-3.4" label="4.3.4">
 1745: <title>Skin Files</title>
 1747: <para>Obviously, we cannot describe even a fraction of the CSS files that
 1748: go into making up a single, overall theme. There are, however, some
 1749: CSS files that help determine how the Mozilla browser looks. In this
 1750: section, we will go over some of those files so you can see how they
 1751: relate to one another, where the browser gets its look, and what
 1752: strategies you might use to create your own complete skin.
 1753: </para>
 1755: <para>The following sections provide a brief, representative sampling of
 1756: the Modern theme. The global skin, the navigator skin, and the
 1757: communicator skin are discussed as they pertain to the Modern theme
 1758: in the Mozilla browser.
 1759: </para>
 1761: <sect3 role="" id="mozilla-CHP-4-SECT-3.4.1" label="">
 1762: <title>Navigator skin</title>
 1764: <para>One of the<indexterm id="IXT-4-1257"><primary>Modern
 1765: theme</primary><secondary>navigator
 1766: skin</secondary></indexterm><indexterm id="IXT-4-1258"><primary>skins</primary><secondary>navigator</secondary></indexterm><indexterm id="IXT-4-1259"><primary>navigator
 1767: skin</primary></indexterm><indexterm id="IXT-4-1260"><primary>themes</primary><secondary>Modern</secondary><tertiary>navigator
 1768: skin</tertiary></indexterm> most specific and complex skin files in
 1769: the Modern theme hierarchy is the <filename>navigator.css</filename>
 1770: file, which contains style information for the browser itself. When
 1771: you look through this skin, you will see rules for such things as the
 1772: Print button. In <link linkend="mozilla-CHP-4-EX-6">Example 4-6</link>, note how several
 1773: selectors are grouped with a single style rule, and how the
 1774: parent-child relationship between elements (see the earlier section
 1775: <link linkend="mozilla-CHP-4-SECT-2.2.7">Section</link> for an explanation of
 1776: this selector) is used to style print buttons appearing in different
 1777: places (i.e., under different element parents) in the UI.
 1778: </para>
 1780: <example id="mozilla-CHP-4-EX-6" label="4-6">
 1781: <title>CSS for print button in navigator skin </title>
 1782: <programlisting>#print-button 
 1783:   {
 1784:     -moz-binding :
 1785:       url("chrome://communicator/skin/menubuttonBindings.xml#menubutton-dual-foo");
 1786:     list-style-image : url("chrome://global/skin/print.gif");
 1787:     margin           : 6px 6px 0px 6px;
 1788:   }
 1789: #print-button[disabled="true"],
 1790: #print-button[disabled="true"]:hover,
 1791: #print-button[disabled="true"]:hover:active,
 1792: #print-button[disabled="true"] &gt; .menubutton-dual-stack &gt; .menubutton-dual-button,
 1793: #print-button[disabled="true"] &gt; .menubutton-dual-stack &gt; 
 1794:     .menubutton-dual-button:hover,
 1795: #print-button[disabled="true"] &gt; .menubutton-dual-stack &gt; 
 1796:     .menubutton-dual-button:hover:active
 1797:   {
 1798:     list-style-image      : url("chrome://global/skin/print-disabled.gif");
 1799:   }
 1800: #print-button &gt; .menubutton-dual-stack &gt; .menubutton-dual-button:hover
 1801:   {
 1802:     list-style-image      : url("chrome://global/skin/print-hover.gif");
 1803:   }
 1804: #print-button &gt; .menubutton-dual-stack &gt; .menubutton-dual-button:hover:active
 1805:   {
 1806:     list-style-image      : url("chrome://global/skin/print-clicked.gif");
 1807:   }
 1808: #print-button &gt; .menubutton-dual-stack &gt; .menubutton-dual-dropmarker-box
 1809:   {
 1810:     margin-left       : 19px;
 1811:     margin-top        : 22px;
 1812:   }</programlisting>
 1813: </example>
 1815: </sect3>
 1817: <sect3 role="" id="mozilla-CHP-4-SECT-3.4.2" label="">
 1818: <title>Global skin</title>
 1820: <para>Almost all<indexterm id="IXT-4-1261"><primary>Modern theme</primary><secondary>global
 1821: skin</secondary></indexterm><indexterm id="IXT-4-1262"><primary>skins</primary><secondary>global</secondary></indexterm><indexterm id="IXT-4-1263"><primary>global
 1822: skin</primary></indexterm><indexterm id="IXT-4-1264"><primary>themes</primary><secondary>Modern</secondary><tertiary>global
 1823: skin</tertiary></indexterm> of the most specific skin files (e.g.,
 1824: <filename>navigator.css</filename>) inherit from the global skin,
 1825: which includes but is not limited to the
 1826: <filename>global.css</filename> file located in
 1827: <emphasis>chrome://modern.jar!/skin/global/skin/</emphasis>.
 1828: </para>
 1830: <para>The global skin includes other stylesheets that define localizable
 1831: settings and general global formatting, which the
 1832: <filename>global.css</filename> file loads at runtime. If you look at
 1833: the top of the <filename>global.css</filename> file as shown in <link linkend="mozilla-CHP-4-EX-7">Example 4-7</link>, you can see the stylesheet import statements
 1834: that collect these skins into a single global skin:
 1835: </para>
 1837: <example id="mozilla-CHP-4-EX-7" label="4-7">
 1838: <title>CSS Import statements in global skin </title>
 1839: <programlisting>/* ===== global.css ======================================================
 1840:    == Styles that apply everywhere.
 1841:    ======================================================================= */
 1842: /* all localizable skin settings shall live here */
 1843: @import url("chrome://global/locale/intl.css");
 1844: @import url("chrome://global/skin/formatting.css");
 1845: @namespace url("<replaceable>");</replaceable>
 1846: /* ::::: XBL bindings ::::: */
 1847: toolbarbutton[type="menu-button"] {
 1848:    -moz-binding: url("chrome://global/skin/globalBindings.xml#toolbar-menu-button");
 1849: }
 1850: .menulist-compact {
 1851:    -moz-binding: 
 1852:       url("chrome://global/content/bindings/menulist.xml#menulist-compact");
 1853: }
 1854: ...</programlisting>
 1855: </example>
 1857: <para>The <filename>global.css</filename> serves as a base into which these
 1858: other skins can be loaded. When you load
 1859: <filename>global.css</filename> into your XUL file by means of a
 1860: <literal>xul-stylesheet</literal> processing instruction, you in
 1861: effect load these skins.
 1862: </para>
 1864: <para>Also included in <link linkend="mozilla-CHP-4-EX-7">Example 4-7</link> are a couple of binding
 1865: attachments, which attach content to elements that match certain
 1866: style rules. On a related note, most global skins on a
 1867: widget-per-widget basis are now included in the binding themselves,
 1868: as opposed to being imported in a global skin, which used to be the
 1869: case. Take this button stylesheet inclusion from the XBL file
 1870: <literal>button.xml</literal> as a case in point:
 1871: </para>
 1873: <programlisting>&lt;resources&gt;
 1874:   &lt;stylesheet src="chrome://global/skin/button.css"/&gt;
 1875: &lt;/resources&gt;</programlisting>
 1877: <para>Here the XBL specific <literal>&lt;stylesheet&gt;</literal> element
 1878: includes the stylesheet, which can be included in a binding and then
 1879: inherited by other button bindings.
 1880: </para>
 1882: </sect3>
 1884: <sect3 role="" id="mozilla-CHP-4-SECT-3.4.3" label="">
 1885: <title>The communicator skin</title>
 1887: <para>Like <filename>global.css</filename>, <indexterm id="IXT-4-1265"><primary>Modern
 1888: theme</primary><secondary>communicator
 1889: skin</secondary></indexterm><indexterm id="IXT-4-1266"><primary>skins</primary><secondary>communicator</secondary></indexterm><indexterm id="IXT-4-1267"><primary>communicator
 1890: skin</primary></indexterm><indexterm id="IXT-4-1268"><primary>themes</primary><secondary>Modern</secondary><tertiary>communicator
 1891: skin</tertiary></indexterm>the <filename>communicator.css</filename>
 1892: file (<link linkend="mozilla-CHP-4-EX-8">Example 4-8</link>) is another CSS file that does
 1893: imports to build up the communicator skin. The CSS style rules in the
 1894: file itself are minimal, but if you look at the top, you can see that
 1895: many styles that the communicator component uses come from the CSS
 1896: files also located in the <filename>communicator</filename>
 1897: subdirectory of the current skin.
 1898: </para>
 1900: <example id="mozilla-CHP-4-EX-8" label="4-8">
 1901: <title>CSS information from communicator.css </title>
 1902: <programlisting>/* ==== communicator.css ====================================================
 1903:    == Styles shared everywhere throughout the Communicator suite.
 1904:    ========================================================================== */
 1905: @import url("chrome://global/skin/");
 1906: @import url("chrome://communicator/content/communicator.css");
 1907: @import url("chrome://communicator/skin/brand.css");
 1908: @import url("chrome://communicator/skin/button.css");
 1909: @import url("chrome://communicator/skin/formatting.css");
 1911: @namespace url("");
 1913: /* ::::: online/offline icons ::::: */
 1915: #offline-status[offline="true"] {
 1916:   list-style-image: url("chrome://communicator/skin/icons/offline.gif");
 1917: }
 1919: #offline-status {
 1920:   list-style-image: url("chrome://communicator/skin/icons/online.gif");
 1921: }
 1923: /* ::::: directional button icons ::::: */
 1925: .up {
 1926:   min-width: 0px;
 1927:   list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
 1928: }
 1930: .up[disabled="true"] {
 1931:   list-style-image: url("chrome://global/skin/arrow/arrow-up-dis.gif");
 1932: }
 1934: .down {
 1935:   min-width: 0px;
 1936:   list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
 1937: }
 1939: .down[disabled="true"] {
 1940:   list-style-image: url("chrome://global/skin/arrow/arrow-dn-dis.gif");
 1941: }
 1943: .up {
 1944:   list-style-image:url("chrome://global/skin/scroll-up.gif");
 1945:   min-width: 0px;
 1946: }
 1947: .up[disabled="true"] {
 1948:   list-style-image:url("chrome://global/skin/scroll-up-disabled.gif");
 1949: }
 1950: .down {
 1951:   min-width: 0px;
 1952:   list-style-image:url("chrome://global/skin/scroll-down.gif");
 1953: }
 1954: .down[disabled="true"] {
 1955:   list-style-image:url("chrome://global/skin/scroll-down-disabled.gif");
 1956: }
 1957: .sidebarTree {
 1958:   border: none;
 1959:   margin: 0px !important;
 1960: }
 1961: /* ::::: download manager ::::: */
 1962: #downloadView &gt; treechildren:-moz-tree-image(Name) {
 1963:   margin-right: 2px;
 1964: }</programlisting>
 1965: </example>
 1967: </sect3>
 1968: </sect2>
 1969: </sect1>
 1971: <sect1 role="" id="mozilla-CHP-4-SECT-4" label="4.4">
 1972: <title>Creating New Skins</title>
 1974: <para>You have
 1975: <indexterm id="IXT-4-1269"><primary>skins</primary><secondary>creating</secondary></indexterm>already
 1976: created the highest level of the directory structure you will need to
 1977: create a skin for the xFly application (See
 1978: "Creating the Hello xFly Package"
 1979: in <link linkend="mozilla-CHP-2">Chapter 2</link>). So far, you have created three
 1980: subdirectories corresponding to different parts of the package and
 1981: you have added XUL to the <filename>xfly/content
 1982: </filename>subdirectory. In the <filename>xfly/skin</filename>
 1983: subdirectory, you will tell the xFly content where to expect to find
 1984: its skin resources. As just mentioned, Mozilla applications outside
 1985: of the browser itself typically restrict their skin to a single
 1986: subdirectory and their skin manifest to a single RDF/XML file.
 1987: </para>
 1989: <para>Since the <filename>skin</filename> subdirectory in your xFly package
 1990: is already registered, you can create a new CSS file called
 1991: <filename>xfly.css</filename>, save it in the <filename>skins
 1992: </filename>subdirectory, and load it from your
 1993: <filename>xfly.xul</filename> file by adding the following stylesheet
 1994: loading instruction at the top:
 1995: </para>
 1997: <programlisting>&lt;?xml-stylesheet href="chrome://xfly/skin" type="text/css" ?&gt;</programlisting>
 1999: <para>You will recall that the chrome pointer in the
 2000: <filename>href</filename> resolves to a file named
 2001: <filename>xfly.css</filename> (named after the directory) in the
 2002: following <emphasis>registered</emphasis> directory in the chrome:
 2003: </para>
 2005: <programlisting>chrome/xfly/skin/</programlisting>
 2007: <para>This CSS file will be the worksheet for all CSS for the xFly
 2008: application. Any style rules you add here and associated with XUL
 2009: elements in the xFly XUL code will affect the layout and presentation
 2010: of that code on restart.
 2011: </para>
 2013: <sect2 role="" id="mozilla-CHP-4-SECT-4.1" label="4.4.1">
 2014: <title>Importing the Global Skin</title>
 2016: <para>As
 2017: you<indexterm id="IXT-4-1270"><primary>skins</primary><secondary>creating</secondary><tertiary>importing
 2018: global skin</tertiary></indexterm><indexterm id="IXT-4-1271"><primary>global
 2019: skin</primary><secondary>importing, creating new
 2020: skins</secondary></indexterm><indexterm id="IXT-4-1272"><primary>importing</primary><secondary>global
 2021: skin, creating new skins</secondary></indexterm> create a new skin
 2022: for your application, the first step is to make sure that the
 2023: application imports the global skin in which the most basic look and
 2024: feel of the XUL widgets is defined. Even if you create a skin that
 2025: looks completely different than the skins installed with Mozilla, you
 2026: should import the global skin to avoid having to recreate so much of
 2027: the basic presentation and behavior of the XUL widgets.
 2028: </para>
 2030: <para>As much as possible, the global skin avoids providing theme-specific
 2031: styles, and instead provides just enough information to make buttons,
 2032: for example, look like buttons and menu items look like menu items.
 2033: Increasingly, basic styles are also being defined in the XBL bindings
 2034: for widgets. For instance, when you use a <literal>toolbar</literal>
 2035: widget, you use a binding in which certain intrinsic looks and
 2036: behaviors are defined in a way that's transparent to
 2037: you and to the user of the application. The style for these bindings
 2038: is located in the content subdirectories with the binding XML files.
 2039: In this way, they "stay with" the
 2040: widget and not with the selected skin. You can easily extend or
 2041: overwrite any of the style information you pick up from the global
 2042: skin, but loading the skin is a good place to start.
 2043: </para>
 2045: <para>To do this, verify that you have the following line at the top of the
 2046: <filename>xfly.xul</filename> file:
 2047: </para>
 2049: <programlisting>&lt;?xml-stylesheet href="chrome://global/skin" type="text/css" ?&gt;</programlisting>
 2051: <para>If you do not have this line, add it now to the
 2052: <filename>xfly.xul</filename> file and restart Mozilla. You ought to
 2053: see a plain, UI-like collection of widgets in the XUL window. In the
 2054: screenshots in <link linkend="mozilla-CHP-4-FIG-8">Figure 4-8</link>, you can see how loading
 2055: the global skin affects the XUL file.
 2056: </para>
 2058: <figure id="mozilla-CHP-4-FIG-8" label="4-8">
 2059: <title>Stylesheet additions to a XUL file</title>
 2060: <graphic fileref="figs/moz_0408.png"/></figure>
 2062: <para>The first screenshot in <link linkend="mozilla-CHP-4-FIG-8">Figure 4-8</link> shows a XUL file
 2063: loaded in Mozilla with no skin information. The second is the same
 2064: XUL file with the global skin loading instruction at the top. The
 2065: third is a screenshot of that XUL file with an instruction for
 2066: loading your own stylesheet, which in turn imports the global skin:
 2067: </para>
 2069: <programlisting>&lt;?xml-stylesheet href="chrome://xfly/skin/sample.css" type="text/css" ?&gt;</programlisting>
 2071: <para>The CSS information in the skin file <filename>sample.css</filename>
 2072: loaded above looks like this:
 2073: </para>
 2075: <programlisting>@import url(chrome://global/skin/)
 2076: box#bbox { background-color: lightgrey; }
 2077: button#rd { background-color: red; color: white; }</programlisting>
 2079: <para>Taking advantage of the modularity of Mozilla skins, you can design a
 2080: decent interface (if the last screenshot above can count as that)
 2081: with just a few lines of code.
 2082: </para>
 2084: <para>Once you import the global skin and see what it buys you in terms of
 2085: look and feel, you can begin to create your own skin for the xFly,
 2086: overriding global styles where appropriate, extending them by
 2087: "cascading" new, more specific
 2088: style rules for your widgets, or adding new styles.
 2089: </para>
 2091: <para>Before you begin to add styles to the <filename>xfly.css</filename>
 2092: file, import it (as a blank skin) into <filename>xfly.xul</filename>
 2093: so you can see your progress as you go. Add the following line to the
 2094: top of the <filename>xfly.xul</filename> file to import the xFly skin
 2095: from the proper subdirectory of the xFly package:
 2096: </para>
 2098: <programlisting>&lt;?xml-stylesheet href="chrome://xfly/skin" type="text/css" ?&gt;</programlisting>
 2100: <para>You won't see anything extra when you quit and
 2101: restart the application, but you now have the skin structure in place
 2102: so you can see your work progress.
 2103: </para>
 2105: </sect2>
 2106: <sect2 role="" id="mozilla-CHP-4-SECT-4.2" label="4.4.2">
 2107: <title>Getting Started with Custom Styles</title>
 2109: <para>When you
 2110: <indexterm id="IXT-4-1273"><primary>skins</primary><secondary>creating</secondary><tertiary>general
 2111: custom styles</tertiary></indexterm><indexterm id="IXT-4-1274"><primary>CSS
 2112: (Cascading Style
 2113: Sheets)</primary><secondary>skins</secondary><tertiary>defining
 2114: general custom styles</tertiary></indexterm>make a new skin,
 2115: it's a good idea to define the most general styles
 2116: for your application first. As we described above, more specific CSS
 2117: rules tend to inherit from more general ones. For the xFly
 2118: application, the most general aspects of the style are the rules that
 2119: apply to the xFly windows themselves. You can create styles for all
 2120: windows using the element name, <filename>window</filename>, or you
 2121: can define different classes for windows if your application supports
 2122: them. In the <filename>xfly.xul</filename> file, for example, the
 2123: root <literal>&lt;window&gt;</literal> element has the attribute
 2124: <literal>class="main"</literal>, so it will pick up style rules given
 2125: for <filename>window.main</filename>, as shown in <link linkend="mozilla-CHP-4-EX-9">Example 4-9</link>. 
 2126: </para>
 2128: <para>The xFly application has both a main window and pop-up windows, so
 2129: you might create style rules like the ones that follow to establish
 2130: the basic look of the xFly application.
 2131: </para>
 2133: <example id="mozilla-CHP-4-EX-9" label="4-9">
 2134: <title>CSS rules for xFly window </title>
 2135: <programlisting>window.main { 
 2136:    background-color:            #cccccc;
 2137:     display:                    block; 
 2138:     overflow:                   hidden;
 2139:     font:                       small arial,helvetica,sans-serif,tahoma;
 2140:     padding:                    0px;
 2141: }
 2142: window.popup{
 2144:     background-color:           #cccccc;
 2145:     display:                    block;
 2146:     overflow:                   hidden;
 2147:     font:                       small arial,helvetica,sans-serif,tahoma;
 2148:     padding:                    2px;
 2149:     width:                      auto;
 2150:     height:                     auto;
 2151: }</programlisting>
 2152: </example>
 2154: <para>Now, with the two stylesheets (<filename>global.css</filename> and
 2155: the <filename>xfly.css</filename>) referenced at the top, you already
 2156: have a window that is starting to look like an application.
 2157: </para>
 2159: </sect2>
 2160: <sect2 role="" id="mozilla-CHP-4-SECT-4.3" label="4.4.3">
 2161: <title>Creating Styles for the xFly Buttons</title>
 2163: <para>Now
 2164: that<indexterm id="IXT-4-1275"><primary>skins</primary><secondary>creating</secondary><tertiary>button
 2165: styles</tertiary></indexterm><indexterm id="IXT-4-1276"><primary>buttons</primary><secondary>styles,
 2166: creating for custom skins</secondary></indexterm> you have created a
 2167: single custom style for the xFly application, you can see how easy it
 2168: is to associate cascading style rules with any element in your
 2169: interface. The next logical step is to style the buttons in the xFly
 2170: sample application, since they make up such a large portion of the
 2171: interface itself.
 2172: </para>
 2174: <para>When you use the button widget without any extra style information,
 2175: you already get a lot of the button-like presentation and behavior.
 2176: The button has different looks, for example, when you hover over it
 2177: and when you click it, and it has a basic three-dimensional shape as
 2178: seen in <link linkend="mozilla-CHP-4-FIG-9">Figure 4-9</link>.
 2179: </para>
 2181: <figure id="mozilla-CHP-4-FIG-9" label="4-9">
 2182: <title>XUL button with no style</title>
 2183: <graphic fileref="figs/moz_0409.png"/></figure>
 2185: <para>A common update to regular XUL buttons is to give them images, like
 2186: the navigation buttons in the main Mozilla browser window. Adding the
 2187: class-based style rule in <link linkend="mozilla-CHP-4-EX-10">Example 4-10</link> to the xFly
 2188: stylesheet (and, of course, the GIF image itself to the
 2189: <filename>skin</filename> subdirectory) will give all the
 2190: "fly" buttons background images
 2191: with flies in them.
 2192: </para>
 2194: <example id="mozilla-CHP-4-EX-10" label="4-10">
 2195: <title>Custom styles for buttons </title>
 2196: <programlisting> {
 2197:   list-style-image: url("chrome://xfly/skin/btnfly.gif");
 2198: }
 2199:[disabled="true"] {
 2200:   list-style-image: url("chrome://xfly/skin/btnfly-dis.gif ");
 2201: }
 2202: {
 2203:   list-style-image: url("chrome://xfly/skin/btnfly-hov.gif ");
 2204: }</programlisting>
 2205: </example>
 2207: </sect2>
 2208: <sect2 role="" id="mozilla-CHP-4-SECT-4.4" label="4.4.4">
 2209: <title>Describing the Skin in RDF</title>
 2211: <para>As described
 2212: <indexterm id="IXT-4-1277"><primary>skins</primary><secondary>creating</secondary><tertiary>RDF
 2213: manifest files</tertiary></indexterm><indexterm id="IXT-4-1278"><primary>RDF
 2214: (Resource Description
 2215: Framework)</primary><secondary>files</secondary><tertiary>creating
 2216: skins</tertiary></indexterm><indexterm id="IXT-4-1279"><primary>manifests</primary><secondary>creating
 2217: skins</secondary></indexterm><indexterm id="IXT-4-1280"><primary>files</primary><secondary>mainfest,
 2218: creating skins</secondary></indexterm>in <link linkend="mozilla-CHP-6">Chapter 6</link>, a manifest must accompany and describe the
 2219: skin so it can be found and registered. The manifest is an RDF file
 2220: called <filename>contents.rdf</filename> that sits at the highest
 2221: level of the skin (i.e., at the top of the JAR or immediately under
 2222: the <filename>modern</filename> directory when extracted to disk).
 2223: Since the content, skin, and locale of an application are considered
 2224: different packages, each must have its own manifest.
 2225: </para>
 2227: <para>The listing in <link linkend="mozilla-CHP-4-EX-11">Example 4-11</link> shows the
 2228: <filename>contents.rdf</filename> manifest that accompanies the xFly
 2229: skin resources in the <filename>xfly.jar!/skin/</filename> directory.
 2230: </para>
 2232: <example id="mozilla-CHP-4-EX-11" label="4-11">
 2233: <title>Skin manifest for the xFly sample </title>
 2234: <programlisting>&lt;?xml version="1.0"?&gt;
 2235: &lt;RDF:RDF xmlns:RDF=" 
 2236:    xmlns:chrome=""&gt;
 2237:   &lt;RDF:Seq about="urn:mozilla:skin:root"&gt;
 2238:     &lt;RDF:li resource="urn:mozilla:skin:classic/1.0" /&gt;
 2239:   &lt;/RDF:Seq&gt;
 2240:   &lt;RDF:Description about="urn:mozilla:skin:classic/1.0"&gt;
 2241:     &lt;chrome:packages&gt;
 2242:       &lt;RDF:Seq about="urn:mozilla:skin:classic/1.0:packages"&gt;
 2243:         &lt;RDF:li resource="urn:mozilla:skin:classic/1.0:xfly"/&gt;
 2244:       &lt;/RDF:Seq&gt;
 2245:     &lt;/chrome:packages&gt;
 2246:   &lt;/RDF:Description&gt;
 2247: &lt;/RDF:RDF&gt;</programlisting>
 2248: </example>
 2250: <para>As you can see, the basic form of the manifest is something like,
 2251: "This is the classic skin we have (given as a direct
 2252: child of the RDF root element), which applies to the following
 2253: packages: <filename>xfly</filename>." The second
 2254: group of RDF in this manifest provides a list of packages to which
 2255: the skin should apply. In the case of the xFly application, all XUL
 2256: code is a single package. In Mozilla, a
 2257: <filename>contents.rdf</filename> file in a package subdirectory of
 2258: the <filename>modern.jar</filename>, for example, would describe the
 2259: communicator package in a similar way, but it would be a composite of
 2260: other package manifests in the theme to create a single, overarching
 2261: manifest for the whole theme. <link linkend="mozilla-CHP-4-EX-12">Example 4-12</link> shows the
 2262: manifest for just the Mozilla communicator package.
 2263: </para>
 2265: <example id="mozilla-CHP-4-EX-12" label="4-12">
 2266: <title>Manifest for the communicator package of the modern skin in Mozilla </title>
 2267: <programlisting>&lt;?xml version="1.0"?&gt;
 2268: &lt;RDF:RDF xmlns:RDF=""
 2269:          xmlns:chrome=""&gt;
 2270:   &lt;!-- List all the skins being supplied by this theme --&gt;
 2271:   &lt;RDF:Seq about="urn:mozilla:skin:root"&gt;
 2272:     &lt;RDF:li resource="urn:mozilla:skin:modern/1.0" /&gt;
 2273:   &lt;/RDF:Seq&gt;
 2274:   &lt;!-- Modern Information --&gt;
 2275:   &lt;RDF:Description about="urn:mozilla:skin:modern/1.0"&gt;
 2276:     &lt;chrome:packages&gt;
 2277:       &lt;RDF:Seq about="urn:mozilla:skin:modern/1.0:packages"&gt;
 2278:         &lt;RDF:li resource="urn:mozilla:skin:modern/1.0:communicator"/&gt;
 2279:       &lt;/RDF:Seq&gt;
 2280:     &lt;/chrome:packages&gt;
 2281:   &lt;/RDF:Description&gt;
 2282: &lt;/RDF:RDF&gt;</programlisting>
 2283: </example>
 2285: <para>This RDF/XML file describes a skin to the chrome registry so it can
 2286: be registered properly. All new packages must be accompanied by these
 2287: sorts of RDF-based descriptions if they will be made available to
 2288: users.
 2289: </para>
 2291: </sect2>
 2292: </sect1>
 2294: <sect1 role="" id="mozilla-CHP-4-SECT-5" label="4.5">
 2295: <title>What Is Possible in a Skin?</title>
 2297: <para>In this final section, we describe a few things that make CSS in
 2298: Mozilla particularly powerful and cases when this power is curtailed
 2299: because of the security restrictions.
 2300: </para>
 2302: <sect2 role="" id="mozilla-CHP-4-SECT-5.1" label="4.5.1">
 2303: <title>Binding New Widgets to the Interface Using XBL</title>
 2305: <para>A <indexterm id="IXT-4-1281"><primary>CSS (Cascading Style
 2306: Sheets)</primary><secondary>widgets, binding with
 2307: XBL</secondary></indexterm><indexterm id="IXT-4-1282"><primary>widgets</primary><secondary>binding
 2308: with
 2309: XBL</secondary></indexterm><indexterm id="IXT-4-1283"><primary>skins</primary><secondary>widgets,
 2310: binding with
 2311: XBL</secondary></indexterm><indexterm id="IXT-4-1284"><primary>bindings</primary><secondary>XBL</secondary><tertiary>widgets</tertiary></indexterm><indexterm id="IXT-4-1285"><primary>XBL
 2312: (eXtensible Binding
 2313: Language)</primary><secondary>widgets</secondary></indexterm>description
 2314: of skins wouldn't be complete without a mention of
 2315: binding widgets by using XBL, a very powerful feature of CSS in
 2316: Mozilla. The <literal>-moz-binding</literal> keyword described in
 2317: <link linkend="mozilla-CHP-4-TABLE-4">Table 4-4</link> is the key to binding special,
 2318: prefabricated widgets to your XUL. The language in which these
 2319: widgets are defined is another XML-based language called the
 2320: Extensible Bindings Language. <link linkend="mozilla-CHP-7">Chapter 7</link> describes
 2321: this language in more detail.
 2322: </para>
 2324: <para>To see how XBL works, go back and look at the first style rule for
 2325: "print-button" in <link linkend="mozilla-CHP-4-EX-6">Example 4-6</link>. The first style statement in that block has a
 2326: property called <literal>-moz-</literal> <literal>binding</literal>.
 2327: This property defines a <filename>binding</filename> for the XUL
 2328: element styled by this style rule. The <filename>chrome URL</filename>
 2329: that the <literal>-moz-binding</literal> property points to is where
 2330: an XBL-based definition of a print button is located.
 2331: </para>
 2333: <para>Creating a style rule in which your XUL element (in this case, a
 2334: button in which the ID is
 2335: "print-button") and the use of the
 2336: <literal>-moz-binding</literal> to point to the XBL defines new
 2337: properties, behavior, or content for that XUL element, you can add to
 2338: or totally recreate any widget in your interface. The binding itself
 2339: is described in XBL, but XBL also provides structures (such as the
 2340: <literal>&lt;content&gt;</literal> and
 2341: <literal>&lt;handlers&gt;</literal> child elements) in which you can
 2342: define new XUL content, new JavaScript, and new XPConnected
 2343: interfaces. CSS glues the XUL together with the XBL.
 2344: </para>
 2346: <para>In the first part of the snippet in <link linkend="mozilla-CHP-4-EX-13">Example 4-13</link>, for
 2347: example, the CSS rule binds the toolbar button to an XBL binding
 2348: called <filename>menu-button</filename>, which adds a button and an
 2349: image.
 2350: </para>
 2352: <example id="mozilla-CHP-4-EX-13" label="4-13">
 2353: <title>CSS and XBL example </title>
 2354: <programlisting>// In the CSS:
 2355: toolbarbutton[type="menu-button"] {
 2356:    -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#menu-button");
 2357: }
 2358: // In the XBL file toolbarbutton.xml:
 2359: &lt;binding id="menu-button" display="xul:menu" 
 2360:     extends="chrome://global/content/bindings/button.xml#menu-button-base"&gt;
 2361:   &lt;resources&gt;
 2362:     &lt;stylesheet src="chrome://global/skin/toolbarbutton.css"/&gt;
 2363:   &lt;/resources&gt;
 2365:   &lt;content&gt;
 2366:     &lt;children includes="observes|template|menupopup|tooltip"/&gt;
 2367:     &lt;xul:toolbarbutton class="box-inherit toolbarbutton-menubutton-button"
 2368:                        anonid="button" flex="1" allowevents="true"
 2369:                        xbl:inherits="disabled,crop,image,label,accessKey,command,
 2370:                                      align,dir,pack,orient"/&gt;
 2371:     &lt;xul:dropmarker type="menu-button" class="toolbarbutton-menubutton-dropmarker"
 2372:                         xbl:inherits="align,dir,pack,orient,disabled"/&gt;
 2373:   &lt;/content&gt;
 2374: &lt;/binding&gt;</programlisting>
 2375: </example>
 2377: <para>When you use the Modern skin, you can see in <link linkend="mozilla-CHP-4-FIG-10">Figure 4-10</link> that the menu button is a composite of the
 2378: toolbar button, a dropmarker image resource, and a
 2379: <literal>menupopup</literal> making the drop-down history available.
 2380: </para>
 2382: <figure id="mozilla-CHP-4-FIG-10" label="4-10">
 2383: <title>Modern menu button</title>
 2384: <graphic fileref="figs/moz_0410.png"/></figure>
 2386: <para>You might also notice in <link linkend="mozilla-CHP-4-EX-13">Example 4-13</link> that this
 2387: binding pulls in an external stylesheet
 2388: (<literal>toolbarbutton.css</literal>), which is contained in the
 2389: <literal>&lt;resources&gt;</literal> section of the binding. This
 2390: stylesheet provides all the styles and theme information for a
 2391: toolbar button, including the type of <literal>menu-button</literal>.
 2392: More information on stylesheets in XBL can be found in <link linkend="mozilla-CHP-7">Chapter 7</link>. 
 2393: </para>
 2395: </sect2>
 2396: <sect2 role="" id="mozilla-CHP-4-SECT-5.2" label="4.5.2">
 2397: <title>User Stylesheets</title>
 2399: <para>In <indexterm id="IXT-4-1286"><primary>user
 2400: stylesheets</primary></indexterm><indexterm id="IXT-4-1287"><primary>stylesheets</primary><secondary>user</secondary></indexterm><indexterm id="IXT-4-1288"><primary>CSS
 2401: (Cascading Style Sheets)</primary><secondary>user
 2402: stylesheets</secondary></indexterm><indexterm id="IXT-4-1289"><primary>userChrome.css</primary></indexterm><indexterm id="IXT-4-1290"><primary>userContent.css</primary></indexterm>addition
 2403: to the many CSS stylesheets that give the user interface its look,
 2404: Mozilla also lets you create personal stylesheets that apply to all
 2405: of the chrome and content you view in the browser. Two CSS files,
 2406: <filename>userChrome.css</filename> and
 2407: <filename>userContent.css</filename>, located in the
 2408: <filename>chrome</filename> subdirectory of your user profile, can
 2409: define rules that apply to all of the Mozilla application interfaces
 2410: and all web pages you view, respectively. When these two files are
 2411: present -- sometimes they are installed in the user profile and
 2412: sometimes you create them yourself -- they come with example rules
 2413: that are commented out. However, you can uncomment them and add your
 2414: own rules to personalize the look of the browser and its content.
 2415: </para>
 2417: <para><link linkend="mozilla-CHP-4-EX-14">Example 4-14</link> shows the default commented rules in
 2418: <filename>userChrome.css</filename>. Note the use of the
 2419: <literal>!important</literal> keyword to specify that these rules
 2420: should take precedence over rules that come from stylesheets in the
 2421: current theme.
 2422: </para>
 2424: <example id="mozilla-CHP-4-EX-14" label="4-14">
 2425: <title>userChrome.css style rules </title>
 2426: <programlisting>/*
 2427:  * This file can be used to customize the look of Mozilla's user interface
 2428:  * You should consider using !important on rules which you want to
 2429:  * override default settings.
 2430:  */
 2431: /*
 2432:  * example: make the UI look a little more like Irix (nice readable
 2433:  *          slanted-helvetical menus, funny pink color on text fields)
 2434:  *
 2435:  * input {
 2436:  *   color: black !important;
 2437:  *   background-color: rgb(255, 225, 175) !important;
 2438:  * }
 2439:  *
 2440:  * menubar {
 2441:  *   font-family: helvetica !important;
 2442:  *   font-style: italic !important;
 2443:  *   font-weight: bold !important;
 2444:  *   font-size: 4mm !important;
 2445:  * }
 2446:  */
 2447: /*
 2448:  * For more examples see
 2449:  */</programlisting>
 2450: </example>
 2452: <para>If you want to make the content in all your <literal>menu</literal>
 2453: widgets white so you can read them better, get rid of these defaults
 2454: and do something like this:
 2455: </para>
 2457: <programlisting>menu { 
 2458:   background-color: white !important;
 2459:   color: darkblue !important;
 2460:   padding: 5px !important;
 2461: }</programlisting>
 2463: <para>You can also use these stylesheets to change or do away with aspects
 2464: of the user interface you don't like. The following
 2465: rule, for example, shrinks the navigation buttons in the Modern
 2466: theme:
 2467: </para>
 2469: <programlisting>.toolbarbutton-menubutton-button &gt; .toolbarbutton-box,
 2470: .toolbarbutton-1 &gt; .toolbarbutton-box
 2471: {
 2472:   max-width: 40px !important;
 2473:   text-align: center !important;
 2474: }</programlisting>
 2476: <para>Or, if you can think of the appropriate selectors, you can use
 2477: <filename>userContent.css</filename> to change the way banner images
 2478: are displayed (or not displayed), how basic text is presented, or
 2479: where certain elements of a web page are positioned.
 2480: </para>
 2482: </sect2>
 2483: <sect2 role="" id="mozilla-CHP-4-SECT-5.3" label="4.5.3">
 2484: <title>Theme Security Restrictions</title>
 2486: <para>To prevent <indexterm id="IXT-4-1291"><primary>themes</primary><secondary>security
 2487: considerations</secondary></indexterm><indexterm id="IXT-4-1292"><primary>security</primary><secondary>themes</secondary></indexterm>the
 2488: wholesale overriding of the basic XUL application, various
 2489: restrictions are placed on themes. In other words, you can do some
 2490: things in XUL that you cannot do in CSS. The two preinstalled themes
 2491: in Mozilla, Modern, and Classic use technologies like XBL,
 2492: JavaScript, and XPConnect to provide additional behavior to the
 2493: application. They are considered full-blown packages, like entirely
 2494: separate interfaces (see <link linkend="mozilla-CHP-6">Chapter 6</link> for a
 2495: description the various types of packages and installations). When
 2496: you install new themes, however, those themes do not have
 2497: "script access" and have limited
 2498: access to XBL bindings.
 2499: </para>
 2501: <para>Code in the <literal>&lt;implementation&gt;</literal> and
 2502: <literal>&lt;handler&gt;</literal> structures of an XBL binding are
 2503: ignored, as are event handlers written in the
 2504: <literal>&lt;content&gt;</literal> structures.
 2505: </para>
 2507: <para>You can write these XBL goodies into your theme if you want (or
 2508: develop a theme out of the Modern theme, where there is plenty of
 2509: XBL, and see them disabled in your theme when they were working in
 2510: that preinstalled version), but Mozilla will not read or execute
 2511: them. You can use XBL to define new XUL content for a widget by way
 2512: of CSS, but unless you create an "evil
 2513: skin," that content has to be simple XUL to show up
 2514: in your theme at all.
 2515: </para>
 2517: <sidebar id="mozilla-CHP-4-SIDEBAR-2">
 2518: <title>Evil Skins</title>
 2520: <para>In the <indexterm id="IXT-4-1293"><primary>evil
 2521: skins</primary></indexterm><indexterm id="IXT-4-1294"><primary>skins</primary><secondary>evil
 2522: skins</secondary></indexterm>Mozilla community, the term
 2523: "evil skins" is sometimes used to
 2524: describe skins with unlimited script access. An evil skin is a skin
 2525: for which the security restrictions above do not apply. They can
 2526: access the DOM of the web page and XUL content, use XPConnect to
 2527: connect to the Mozilla services in XPCOM, or implement new
 2528: application code in XBL widgets.
 2529: </para>
 2531: <para>Remember that when you develop skins for Mozilla and package them for
 2532: installation as skins, the script part of your skins will be
 2533: disabled. However, if you create a skin and then install it as a new
 2534: package, your skin will not be as limited, and you will have full
 2535: access to XBL, XPConnect, and the script. To see how to install an
 2536: evil skin and other new packages in Mozilla, see <link linkend="mozilla-CHP-6">Chapter 6</link>. 
 2537: </para>
 2538: </sidebar>
 2542: </sect2>
 2543: </sect1>
 2544: </chapter>

FreeBSD-CVSweb <>