Theme"
m (correct highlight (via JWB)) |
|||
Line 5: | Line 5: | ||
The look and feel of ZK components are fully controlled with CSS. Depending on the level of customization, there are several approaches. | The look and feel of ZK components are fully controlled with CSS. Depending on the level of customization, there are several approaches. | ||
− | # If you want to change the font size and family for the whole application, you can specify the corresponding library properties in < | + | # If you want to change the font size and family for the whole application, you can specify the corresponding library properties in <code>WEB-INF/zk.xml</code>. |
− | # If you want to add your own CSS file, you can specify them in < | + | # If you want to add your own CSS file, you can specify them in <code>WEB-INF/zk.xml</code>. |
# If you want a totally control, you can implement a theme provider. | # If you want a totally control, you can implement a theme provider. | ||
Line 35: | Line 35: | ||
| <center>org.zkoss.zul.theme.fontSizeS</center> | | <center>org.zkoss.zul.theme.fontSizeS</center> | ||
| <center>11px</center> | | <center>11px</center> | ||
− | | The smaller font size used in the component that requires small fonts, such as < | + | | The smaller font size used in the component that requires small fonts, such as <code>toolbar</code>. |
|- | |- | ||
Line 48: | Line 48: | ||
|} | |} | ||
− | To change the default value, you can specify the library properties in < | + | To change the default value, you can specify the library properties in <code>WEB-INF/zk.xml</code> as follows. |
<source lang="xml" > | <source lang="xml" > | ||
Line 74: | Line 74: | ||
|- | |- | ||
| org.zkoss.zul.theme.fontFamilyT | | org.zkoss.zul.theme.fontFamilyT | ||
− | | Default: < | + | | Default: <code>Verdana, Tahoma, Arial, Helvetica, sans-serif</code> |
The font family used for titles and captions. | The font family used for titles and captions. | ||
Line 80: | Line 80: | ||
|- | |- | ||
| org.zkoss.zul.theme.fontFamilyC | | org.zkoss.zul.theme.fontFamilyC | ||
− | | Default: < | + | | Default: <code>Verdana, Tahoma, Arial, serif</code> |
The font family used for conntents. | The font family used for conntents. | ||
Line 88: | Line 88: | ||
== Add Additional CSS == | == Add Additional CSS == | ||
− | If you want to customize certain components, you can provide a CSS file to override the default setting. For example, if you want to customize the look and feel of the < | + | If you want to customize certain components, you can provide a CSS file to override the default setting. For example, if you want to customize the look and feel of the <code>a</code> component, you can provide a CSS file with the following content. |
<source lang="css"> | <source lang="css"> | ||
Line 101: | Line 101: | ||
</source> | </source> | ||
− | Then, specify it in < | + | Then, specify it in <code>WEB-INF/zk.xml</code> as follows. |
<source lang="xml" > | <source lang="xml" > | ||
Line 115: | Line 115: | ||
=== Use the Built-in Theme with Smaller Fonts === | === Use the Built-in Theme with Smaller Fonts === | ||
− | The theme with smaller fonts is called < | + | The theme with smaller fonts is called <code>normsm*.css.dsp</code>. You can configure <code>WEB-INF/zk.xml</code> to use it as follows. |
<source lang="xml" > | <source lang="xml" > | ||
Line 124: | Line 124: | ||
</source> | </source> | ||
− | Refer to the '''Developer's Reference''' for more about how to configure with < | + | Refer to the '''Developer's Reference''' for more about how to configure with <code>WEB-INF/zk.xml</code>. |
=== Use the Built-in Theme with Larger Fonts === | === Use the Built-in Theme with Larger Fonts === | ||
− | The theme with larger fonts is called < | + | The theme with larger fonts is called <code>normlg*.css.dsp</code>. You can configure <code>WEB-INF/zk.xml</code> to use it as follows. |
<source lang="xml" > | <source lang="xml" > | ||
Line 137: | Line 137: | ||
=== Use the Theme that Depends on Locale === | === Use the Theme that Depends on Locale === | ||
− | It is common to use the larger font only for Chinese locales. You can configure < | + | It is common to use the larger font only for Chinese locales. You can configure <code>WEB-INF/zk.xml</code> to use it as follows. |
<source lang="xml" > | <source lang="xml" > | ||
Line 151: | Line 151: | ||
|}} | |}} | ||
− | If you prefer to decide the theme at the run time depending on the current user, cookie, locale or others, you can implement a theme provider. A theme provider is a class that implements the < | + | If you prefer to decide the theme at the run time depending on the current user, cookie, locale or others, you can implement a theme provider. A theme provider is a class that implements the <code>org.zkoss.zk.ui.util.ThemeProvider</code> interface. |
=== ZK 5 Theme Provider === | === ZK 5 Theme Provider === | ||
Line 212: | Line 212: | ||
</source> | </source> | ||
− | Notice that we return -1 when < | + | Notice that we return -1 when <code>getWCSCacheControl</code> is called to disallow the browser to cache the CSS file. It is necessary since we manipulate the content of the CSS file by setting the attributes (based on the cookie). It means the content might be different with the same request URL. You might refer to [[#A Cacheable Example]] for the technique to make the CSS file cacheable. |
− | Then, you configure < | + | Then, you configure <code>WEB-INF/zk.xml</code> by adding the following lines. |
<source lang="xml" > | <source lang="xml" > | ||
Line 224: | Line 224: | ||
==== A Cacheable Example ==== | ==== A Cacheable Example ==== | ||
− | To improve the performance, it is better to allow the browser to cache the CSS file as long as possible. With the theme provider, it can be done by returning a positive number when the < | + | To improve the performance, it is better to allow the browser to cache the CSS file as long as possible. With the theme provider, it can be done by returning a positive number when the <code>getWCSCacheControl</code> is called. However, because the browser will use the cached version, we have to ensure the browser gets a different URL for each different theme. Here is we illustrate a technique called '''fragment injection'''. |
− | The idea is simple: when < | + | The idea is simple: when <code>getThemeURIs</code> is called, we '''inject''' a special fragment to denote the content, such that each different theme is represented with a different URL. The injection can be done easily with the inner class called <code>Aide</code>. For example, |
<source lang="java"> | <source lang="java"> | ||
Line 241: | Line 241: | ||
</source> | </source> | ||
− | Then, we can retrieve the fragment we encoded into the URI later when < | + | Then, we can retrieve the fragment we encoded into the URI later when <code>beforeWCS</code> is called. It can be done easily by use of the <code>decodeURI</code> method (of <code>Aide</code>). The <code>decodeURI</code> method returns a two-element array if the fragment is found. The first element is the URI without fragment, and the second element is the fragment. For example, |
<source lang="java"> | <source lang="java"> | ||
Line 382: | Line 382: | ||
}</source> | }</source> | ||
− | Then, you configure < | + | Then, you configure <code>WEB-INF/zk.xml</code> by adding the following lines. |
<source lang="xml" > | <source lang="xml" > | ||
Line 390: | Line 390: | ||
</source> | </source> | ||
− | '''See also''' < | + | '''See also''' <code>org.zkoss.zkdemo.userguide.FontSizeThemeProvider</code> in <code>zkdemo.war</code> that decides the theme based on cookie. |
{{ ZKDevelopersGuidePageFooter}} | {{ ZKDevelopersGuidePageFooter}} |
Latest revision as of 10:41, 19 January 2022
This documentation is for an older version of ZK. For the latest one, please click here.
Themes
The look and feel of ZK components are fully controlled with CSS. Depending on the level of customization, there are several approaches.
- If you want to change the font size and family for the whole application, you can specify the corresponding library properties in
WEB-INF/zk.xml
. - If you want to add your own CSS file, you can specify them in
WEB-INF/zk.xml
. - If you want a totally control, you can implement a theme provider.
Change Font Size and Family
This documentation is for an older version of ZK. For the latest one, please click here.
The default theme of ZK components use the library properties to control the font size and family. You can change them easily by specifying different values.
Notice that the library properties control the theme for the whole application. If you want to provide per-user theme (like zkdemo does), you have to implement a theme provider.
Font Size
The default theme uses the following library properties to control the font sizes.
The default font size. It is used in the most components. | ||
The smaller font size used in the component that requires small fonts, such as toolbar .
| ||
The extremely small font size; rarely used. | ||
The font size used in the menu items. |
To change the default value, you can specify the library properties in WEB-INF/zk.xml
as follows.
<library-property>
<name>org.zkoss.zul.theme.fontSizeM</name>
<value>12px</value>
</library-property>
<library-property>
<name>org.zkoss.zul.theme.fontSizeS</name>
<value>10px</value>
</library-property>
<library-property>
<name>org.zkoss.zul.theme.fontSizeXS</name>
<value>9px</value>
</library-property>
Font Family
The following library properties control the font family.
org.zkoss.zul.theme.fontFamilyT | Default: Verdana, Tahoma, Arial, Helvetica, sans-serif
The font family used for titles and captions. |
org.zkoss.zul.theme.fontFamilyC | Default: Verdana, Tahoma, Arial, serif
The font family used for conntents. |
Add Additional CSS
If you want to customize certain components, you can provide a CSS file to override the default setting. For example, if you want to customize the look and feel of the a
component, you can provide a CSS file with the following content.
.z-a-disd {
color: #C5CACB !important; cursor: default!important;
text-decoration: none !important;
}
.z-a-disd:visited, .z-a-disd:hover {
text-decoration: none !important; cursor: default !important;;
border-color: #D0DEF0 !important;
}
Then, specify it in WEB-INF/zk.xml
as follows.
<desktop-config>
<theme-uri>/css/my.css</theme-uri>
</desktop-config>
Please refer to the Style Guide for details.
Use Built-in CSS Files
Notice the use of the built-in CSS files is deprecated since ZK 5.
Use the Built-in Theme with Smaller Fonts
The theme with smaller fonts is called normsm*.css.dsp
. You can configure WEB-INF/zk.xml
to use it as follows.
<desktop-config>
<disable-theme-uri>~./zul/css/norm*.css.dsp*</disable-theme-uri>
<theme-uri>~./zul/css/normsm*.css.dsp*</theme-uri>
</desktop-config>
Refer to the Developer's Reference for more about how to configure with WEB-INF/zk.xml
.
Use the Built-in Theme with Larger Fonts
The theme with larger fonts is called normlg*.css.dsp
. You can configure WEB-INF/zk.xml
to use it as follows.
<desktop-config>
<disable-theme-uri>~./zul/css/norm*.css.dsp*</disable-theme-uri>
<theme-uri>~./zul/css/normlg*.css.dsp*</theme-uri>
</desktop-config>
Use the Theme that Depends on Locale
It is common to use the larger font only for Chinese locales. You can configure WEB-INF/zk.xml
to use it as follows.
<desktop-config>
<disable-theme-uri>~./zul/css/norm*.css.dsp*</disable-theme-uri>
<theme-uri>~./zul/css/norm**.css.dsp</theme-uri>
</desktop-config>
Implement a Theme Provider
This documentation is for an older version of ZK. For the latest one, please click here.
If you prefer to decide the theme at the run time depending on the current user, cookie, locale or others, you can implement a theme provider. A theme provider is a class that implements the org.zkoss.zk.ui.util.ThemeProvider
interface.
ZK 5 Theme Provider
We illustrate the theme provider with two examples. One is straightforward: set the corresponding attributes based on the cookie. The other injects a fragment to the URI such that we can allow the client to cache the CSS file.
A Simple Example
Here is an example for ZK 5 theme provider. In the following example, we store the preferred font size and the skin (theme) in the cookie and retrieve them when required.
package my;
public class MyThemeProvider implements ThemeProvder {
public Collection getThemeURIs(Execution exec, List uris) {
if ("silvergray".equals(getSkinCookie(exec))) {
uris.add("~./silvergray/color.css.dsp");
uris.add("~./silvergray/img.css.dsp");
}
return uris;
}
public int getWCSCacheControl(Execution exec, String uri) {
return -1;
}
public String beforeWCS(Execution exec, String uri) {
final String fsc = getFontSizeCookie(exec);
if ("lg".equals(fsc)) {
exec.setAttribute("fontSizeM", "15px");
exec.setAttribute("fontSizeMS", "13px");
exec.setAttribute("fontSizeS", "13px");
exec.setAttribute("fontSizeXS", "12px");
} else if ("sm".equals(fsc)) {
exec.setAttribute("fontSizeM", "10px");
exec.setAttribute("fontSizeMS", "9px");
exec.setAttribute("fontSizeS", "9px");
exec.setAttribute("fontSizeXS", "8px");
}
return uri;
}
public String beforeWidgetCSS(Execution exec, String uri) {
return uri;
}
/** Returns the font size specified in cooke. */
private static String getFontSizeCookie(Execution exec) {
Cookie[] cookies = ((HttpServletRequest)exec.getNativeRequest()).getCookies();
if (cookies!=null)
for (int i=0; i<cookies.length; i++)
if ("myfontsize".equals(cookies[i].getName()))
return cookies[i].getValue();
return "";
}
/** Returns the skin specified in cookie. */
private static String getSkinCookie(Execution exec) {
Cookie[] cookies = ((HttpServletRequest)exec.getNativeRequest()).getCookies();
if (cookies!=null)
for (int i=0; i<cookies.length; i++)
if ("myskin".equals(cookies[i].getName()))
return cookies[i].getValue();
return "";
}
}
Notice that we return -1 when getWCSCacheControl
is called to disallow the browser to cache the CSS file. It is necessary since we manipulate the content of the CSS file by setting the attributes (based on the cookie). It means the content might be different with the same request URL. You might refer to #A Cacheable Example for the technique to make the CSS file cacheable.
Then, you configure WEB-INF/zk.xml
by adding the following lines.
<desktop-config>
<theme-provider-class>my.MyThemeProvider</theme-provider-class>
</desktop-config>
A Cacheable Example
To improve the performance, it is better to allow the browser to cache the CSS file as long as possible. With the theme provider, it can be done by returning a positive number when the getWCSCacheControl
is called. However, because the browser will use the cached version, we have to ensure the browser gets a different URL for each different theme. Here is we illustrate a technique called fragment injection.
The idea is simple: when getThemeURIs
is called, we inject a special fragment to denote the content, such that each different theme is represented with a different URL. The injection can be done easily with the inner class called Aide
. For example,
final String fsc = getFontSizeCookie(exec);
if (fsc != null && fsc.length() > 0) {
for (ListIterator it = uris.listIterator(); it.hasNext();) {
final String uri = (String)it.next();
if (uri.startsWith(DEFAULT_WCS)) {
it.set(Aide.injectURI(uri, fsc));
break;
}
}
}
Then, we can retrieve the fragment we encoded into the URI later when beforeWCS
is called. It can be done easily by use of the decodeURI
method (of Aide
). The decodeURI
method returns a two-element array if the fragment is found. The first element is the URI without fragment, and the second element is the fragment. For example,
public String beforeWCS(Execution exec, String uri) {
final String[] dec = Aide.decodeURI(uri);
if (dec != null) {
if ("lg".equals(dec[1])) {
exec.setAttribute("fontSizeM", "15px");
exec.setAttribute("fontSizeMS", "13px");
exec.setAttribute("fontSizeS", "13px");
exec.setAttribute("fontSizeXS", "12px");
} else if ("sm".equals(dec[1])) {
exec.setAttribute("fontSizeM", "10px");
exec.setAttribute("fontSizeMS", "9px");
exec.setAttribute("fontSizeS", "9px");
exec.setAttribute("fontSizeXS", "8px");
}
return dec[0];
}
return uri;
}
Here is a complete example:
public class CacheableThemeProvider implements ThemeProvider{
private static String DEFAULT_WCS = "~./zul/css/zk.wcs";
public Collection getThemeURIs(Execution exec, List uris) {
//font-size
final String fsc = getFontSizeCookie(exec);
if (fsc != null && fsc.length() > 0) {
for (ListIterator it = uris.listIterator(); it.hasNext();) {
final String uri = (String)it.next();
if (uri.startsWith(DEFAULT_WCS)) {
it.set(Aide.injectURI(uri, fsc));
break;
}
}
}
//slivergray
if ("silvergray".equals(getSkinCookie(exec))) {
uris.add("~./silvergray/color.css.dsp");
uris.add("~./silvergray/img.css.dsp");
}
return uris;
}
public int getWCSCacheControl(Execution exec, String uri) {
return 8760; //safe to cache
}
public String beforeWCS(Execution exec, String uri) {
final String[] dec = Aide.decodeURI(uri);
if (dec != null) {
if ("lg".equals(dec[1])) {
exec.setAttribute("fontSizeM", "15px");
exec.setAttribute("fontSizeMS", "13px");
exec.setAttribute("fontSizeS", "13px");
exec.setAttribute("fontSizeXS", "12px");
} else if ("sm".equals(dec[1])) {
exec.setAttribute("fontSizeM", "10px");
exec.setAttribute("fontSizeMS", "9px");
exec.setAttribute("fontSizeS", "9px");
exec.setAttribute("fontSizeXS", "8px");
}
return dec[0];
}
return uri;
}
public String beforeWidgetCSS(Execution exec, String uri) {
return uri;
}
/** Returns the font size specified in cooke. */
private static String getFontSizeCookie(Execution exec) {
Cookie[] cookies = ((HttpServletRequest)exec.getNativeRequest()).getCookies();
if (cookies!=null)
for (int i=0; i<cookies.length; i++)
if ("myfontsize".equals(cookies[i].getName()))
return cookies[i].getValue();
return "";
}
/** Returns the skin specified in cookie. */
private static String getSkinCookie(Execution exec) {
Cookie[] cookies = ((HttpServletRequest)exec.getNativeRequest()).getCookies();
if (cookies!=null)
for (int i=0; i<cookies.length; i++)
if ("myskin".equals(cookies[i].getName()))
return cookies[i].getValue();
return "";
}
}
How to Specify the Media Types
[since 5.0.3]
In additions to String instances, you can return instances of StyleSheet in the returned collection of ThemeProvider.getThemeURIs(Execution, List), such that you can control more about the generated CSS link. For example, if you want to add a CSS link for the media type, say, print, handheld
, then you can do as follows.
public Collection getThemeURIs(Execution exec, List uris) {
uris.add(new StyleSheet("/theme/foo.css", "text/css", "print, handheld", false));
return uris;
}
ZK 3 Theme Provider
Here is an example for ZK 3 theme provider. In this example, we remove the default theme and add a custom CSS file based on user's preference (stored in cookie).
package my;
public class MyThemeProvider implements ThemeProvder {
public Collection getThemeURIs(Execution exec, List uris) {
for (Iterator it = uris.iterator(); it.hasNext();)
if ("~./zul/css/norm*.css.dsp*".equals(it.next()))
it.remove(); //remove the default theme
HttpServletRequest req = (HttpServletRequest)exec.getNativeRequest();
uris.add(getMyThemeURI(exec));
return uris;
}
private static String getMyThemeURI(Execution exec) {
Cookie[] cookies = ((HttpServletRequest)exec.getNativeRequest()).getCookies();
if (cookies!=null)
for (int i=0; i<cookies.length; i++)
if ("myfavor".equals(cookies[i].getName())) {
String val = cookies[i].getValue()
if ("red".equals(val))
return "/css/red.css";
else if ("blue".equals(val))
return "/css/blue.css";
return "/css/grey.css";
}
}
}
Then, you configure WEB-INF/zk.xml
by adding the following lines.
<desktop-config>
<theme-provider-class>my.MyThemeProvider</theme-provider-class>
</desktop-config>
See also org.zkoss.zkdemo.userguide.FontSizeThemeProvider
in zkdemo.war
that decides the theme based on cookie.