Background Url Path in a Jsf Template

Background url path in a jsf template

CSS background images are loaded relative to the request URL of the CSS file (and thus not immediately relative to its physical location in the web content). If you explore the generated HTML output of the <h:outputStylesheet>, then you'll see that the request URL has become different. Assuming a context path of /somecontext and a FacesServlet mapping of *.xhtml, it'll look like this:

<link rel="stylesheet" type="text/css" href="/somecontext/javax.faces.resource/cssLayout.css.xhtml?ln=css" />

Note that your (improper btw) usage of the library has moved the /css to ?ln=css. You'd need to fix the background image url() accordingly so that it's properly relative to the real request URL of the CSS. E.g.

background-image: url("../resources/css/imgSite/sisLogo.png");

A more reliable way, which takes JSF resource identifier rules and FacesServlet mapping into account, is to use #{resource} in EL:

background-image: url("#{resource['css:imgSite/sisLogo.png']}");

See also:

  • Changing JSF prefix to suffix mapping forces me to reapply the mapping on CSS background images
  • What is the JSF resource library for and how should it be used?

How to reference JSF image resource as CSS background image url

When importing CSS stylesheets by <h:outputStylesheet>, the stylesheet is imported and processed by the FacesServlet through /javax.faces.resource/*. Look at the generated <link> element pointing to the stylesheet in question and you'll understand.

You have to change all url() dependencies to use #{resource['library:location']} instead. JSF will then auto-substitute it with the right path. Given your folder structure, you need to replace

.c2 {
background: url("/resources/images/smiley.jpg");
}

by

.c2 {
background: url("#{resource['images/smiley.jpg']}");
}

Assuming that your webapp context name is playground and that your FacesServlet is mapped on *.xhtml, then the above should end up in the returned CSS file as follows

.c2 {
background: url("/playground/javax.faces.resource/images/smiley.jpg.xhtml");
}

Noted should be that the JSF implementation will for determine only during the first request on the CSS file if it contains EL expressions. If it doesn't then it will for efficiency not anymore attempt to EL-evaluate the CSS file content. So if you add an EL expression to a CSS file for the first time, then you'd need to restart the whole application in order to get JSF to re-check the CSS file.

In case you wanted to reference a resource from a component library such as PrimeFaces, then prefix the library name, separated with :. E.g. when you're using PrimeFaces "Start" theme which is identified by primefaces-start

.c2 {
background: url("#{resource['primefaces-start:images/ui-bg_gloss-wave_50_6eac2c_500x100.png']}");
}

This will be generated as

.c2 {
background: url("/playground/javax.faces.resource/images/ui-bg_gloss-wave_50_6eac2c_500x100.png.xhtml?ln=primefaces-start");
}

See also:

  • How to reference CSS / JS / image resource in Facelets template?
  • Changing JSF prefix to suffix mapping forces me to reapply the mapping on CSS background images

Unrelated to the concrete problem, the way how you use the library is not entirely right. It's meant to be the common identifier/subfolder of all related CSS/JS/image resources. The key idea is to be able to change the entire look'n'feel by just changing the library (which can be done by EL). You seem however to be relying on the default library. In that case, you could just omit the library from your <h:outputStylesheet> and #{resource}.

<h:outputStylesheet name="css/style.css"  />

See also:

  • What is the JSF resource library for and how should it be used?

How do I add background images in a JSF application using richfaces and CSS?

Assuming the element in question is getting a class="rich-ddmenu-label" applied to it, the problem is likely the path to the background image.

The path is relative to where the CSS is located. If it's in an external file, it should be relative to that, e.g.:

/css/styles.css
/images/the_image.gif

the CSS should be:

background-image: url("../images/the_image.gif");

If the CSS is inline on the HTML page, it will be relative to the current path. So if the page is located at http://server/path/to/page, it will look for the image at http://server/path/to/page/images/the_image.gif, when you probably meant http://server/images/the_image.gif.

If that doesn't answer it, please post the generated HTML.

How to reference CSS / JS / image resource in Facelets template?

Introduction

The proper JSF 2.x way is using <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> with a name referring the path relative to webapp's /resources folder. This way you don't need to worry about the context path as you would do in JSF 1.x. See also How to include CSS relative to context path in JSF 1.x?

Folder structure

Drop the CSS/JS/image files in /resources folder of the public webcontent as below (just create one if not already exist at the same level as /WEB-INF and /META-INF).

WebContent
|-- resources
| |-- css
| | |-- other.css
| | `-- style.css
| |-- js
| | `-- script.js
| `-- images
| |-- background.png
| |-- favicon.ico
| `-- logo.png
|-- META-INF
| `-- MANIFEST.MF
|-- WEB-INF
| |-- faces-config.xml
| `-- web.xml
|-- page.xhtml
:

In case of Maven, it should be in /main/webapp/resources and thus not /main/resources (those are for Java resources (properties/xml/text/config files) which must end up in runtime classpath, not in webcontent). See also Maven and JSF webapp structure, where exactly to put JSF resources.

Referencing in Facelets

Ultimately, those resources are available as below everywhere without the need to fiddle with relative paths:

<h:head>
...
<h:outputStylesheet name="css/style.css" />
<h:outputScript name="js/script.js" />
</h:head>
<h:body>
...
<h:graphicImage name="images/logo.png" />
...
</h:body>

The name attribute must represent the full path relative to the /resources folder. It does not need to start with /. You do not need the library attribute as long as you aren't developing a component library like PrimeFaces or a common module JAR file which is shared by multiple webapps.

You can reference the <h:outputStylesheet> anywhere, also in <ui:define> of template clients without the need for an additional <h:head>. It will via the <h:head> component of master template automatically end up in generated <head>.

<ui:define name="...">
<h:outputStylesheet name="css/style.css" />
...
</ui:define>

You can reference <h:outputScript> also anywhere, but it will by default end up in the HTML exactly there where you declared it. If you want it to end up in <head> via <h:head>, then add target="head" attribute.

<ui:define name="...">
<h:outputScript name="js/script.js" target="head" />
...
</ui:define>

Or, if you want it to end up at the end of <body> (right before </body>, so that e.g. window.onload and $(document).ready() etc isn't necessary) via <h:body>, then add target="body" attribute.

<ui:define name="...">
<h:outputScript name="js/script.js" target="body" />
...
</ui:define>

PrimeFaces HeadRenderer

In case you're using PrimeFaces, its HeadRenderer will messup the default <h:head> script ordering as described above. You're basically forced to force the order via PrimeFaces-specific <f:facet name="first|middle|last">, which may end up in messy and "untemplateable" code. You may want to turn off it as described in this answer.

Packaging in JAR

You can even package the resources in a JAR file. See also Structure for multiple JSF projects with shared code.

Referencing in EL

You can in EL use the #{resource} mapping to let JSF basically print a resource URL like /context/javax.faces.resource/folder/file.ext.xhtml?ln=library so that you could use it as e.g. CSS background image or favicon. Only requirement is that the CSS file itself should also be served as a JSF resource, otherwise EL expressions won't evaluate. See also How to reference JSF image resource as CSS background image url.

.some {
background-image: url("#{resource['images/background.png']}");
}

Here's the @import example.

@import url("#{resource['css/other.css']}");

Here's the favicon example. See also Add favicon to JSF project and reference it in <link>.

<link rel="shortcut icon" href="#{resource['images/favicon.ico']}" />

In case you're using a SCSS compiler (e.g. Sass Compiler Plugin for Maven), keep in mind that the SCSS processor might interpret # as a special character. In that case you would need to escape it with \.

.some {
background-image: url("\#{resource['images/background.png']}");
}

Referencing third-party CSS files

Third party CSS files loaded via <h:outputStylesheet> which in turn reference fonts and/or images may need to be altered to use #{resource} expressions as described in previous section, otherwise an UnmappedResourceHandler needs to be installed in order to be able to serve those using JSF. See also a.o. Bootsfaces page shows up in browser without any styling and How to use Font Awesome 4.x CSS file with JSF? Browser can't find font files.

Hiding in /WEB-INF

If you intend to hide the resources from public access by moving the whole /resources folder into /WEB-INF, then you can since JSF 2.2 optionally change the webcontent-relative path via a new web.xml context parameter as follows:

<context-param>
<param-name>javax.faces.WEBAPP_RESOURCES_DIRECTORY</param-name>
<param-value>/WEB-INF/resources</param-value>
</context-param>

In older JSF versions this is not possible.

See also:

  • Java EE 6 tutorial - Facelets - Resources (which is only 2 chapters away from your link)
  • What is the JSF resource library for and how should it be used?
  • How do I override default PrimeFaces CSS with custom styles?

Accessing images with CSS url() in Primefaces

It looks like your question is more concerned with the client-side aspects of things, so even though I don't know Primefaces, here's a stab at answering it:

CSS paths are relative to the location of where the CSS rule is declared.

If this is in your HTML (in a <style> block), then disk.png has to be in the same directory as your file.

If this rule is in a separate CSS file, then disk.png should be in the directory where the CSS file is.

If you create a directory images, then the directory will be relative from the CSS too.

Hope this helps?

Templating and trying to reference context path from inside a CSS file

Those paths are relative to the request URL of the CSS file itself. It seems pretty trivial to me to group them at the same root level as the CSS file itself. E.g. /css for CSS files and /css/images for CSS background images. This way you can use url('images/name.ext') all the way.

I don't see how it is useful to change the paths everytime. Just keep them consistent and if necessary document it clearly so that it's clear to everyone now and in the future.

I have to add .xhtml to image in css

when .xhtml is appended to the end of a file the url is :

javax.faces.resource/...

while if you want to access a .js file directly for example the url is :

resources/script/myscript.js

don't forget the s in resources.

How to include JSF template in different folder

Add a slash in front of your template location like this:

<ui:composition template="/template/layout.xhtml">
</ui:compostion>

This should work. The location template/layout.xhtml is relative to the "current folder", which will mean JSF will try to load /home/template/layout.xhtml.

Changing JSF prefix to suffix mapping forces me to reapply the mapping on CSS background images

and then I see that everything going through FacesServlet has .xhtml appended to it, so that the browser is requesting .png.xhtml files, .css.xhtml file - is this right?

This only applies to resources included by <h:outputStylesheet> and <h:outputScript>. This is not related to the change in the URL mapping. This is related to the change from JSF 1.x to JSF 2.x and the change from <link rel="stylesheet"> and <script> to the aforementioned JSF2 tags.

For your own scripts, stylesheets and other static stuff which is to be served from the public webcontent, you should not manually add the .xhtml extension. You should not need to change anything with regard to existing static resources.

Only for CSS background images and other url() references in CSS files which is to be included using the <h:outputStylesheet> tag (and thus not for <link rel="stylesheet>), you would need to change the url() location to be dynamically resolved by EL. You would need to use the following syntax instead:

body {
background-image: url("#{resource['libraryname:path/to/image.png']}");
}

Imagine that you have the following /resources folder structure:

WebContent
|-- META-INF
|-- resources
| `-- default
| |-- images
| | `-- background.png
| `-- css
| `-- style.css
|-- WEB-INF
`-- test.xhtml

and that you're including the style.css in test.xhtml as follows

<h:outputStylesheet library="default" name="css/style.css" />

then you should be defining the background image URL as follows

body {
background-image: url("#{resource['default:images/background.png']}");
}

Or when you're relying on the default library, thus you aren't using the library, then it should rather look like this:

WebContent
|-- META-INF
|-- resources
| |-- images
| | `-- background.png
| `-- css
| `-- style.css
|-- WEB-INF
`-- test.xhtml

test.xhtml:

<h:outputStylesheet name="css/style.css" />

style.css:

body {
background-image: url("#{resource['images/background.png']}");
}

As to the securiry constraint, it is not needed when you're already using the *.xhtml mapping. The security constraint is intended to prevent the enduser from seeing the raw XHTML source code when the FacesServlet is mapped on a pattern other then *.xhtml. The enduser would be able to see the XHTML source code by just removing /faces part from the URL in case of a /faces/* mapping or renaming .jsf to .xhtml in case of a *.jsf mapping. Get rid of the security constraint, it makes in your case things worse as you're already using a *.xhtml mapping which makes it already impossible to see the raw XHTML source code by hacking the URL.



Related Topics



Leave a reply



Submit