Can I use EL for external CSS files with JSF?
Asked Answered
B

6

6

In external style sheets of my current JSF project, there are hard-coded links to external resources like

.someId { background-image:url(/context/resources/images/example.jpg); }

In the JSF xhtml documents, I could use EL expressions like ${request.contextPath} but how can EL processing be applied to CSS files?

(Related: How can I embed an CSS background image link with JSF?)


Hard-coding of context paths has a disadvantage: the context path - /context in the example - of a web application can be changed at deploy time by modifying the web.xml (or by renaming the web application archive file if no context is specified in web.xml), but links to resources in the CSS files would still point to the unchanged hard coded context, and cause resource not found errors.

Braggadocio answered 1/5, 2011 at 8:56 Comment(0)
O
10

I put the CSS images always in a subfolder of the CSS folder. E.g.

  • /resources/css/style.css
  • /resources/css/images/example.jpg

This way you just end up like

.someId { background-image:url(images/example.jpg); }

Yes, they are resolved relative to the URL of the CSS file itself, not to the main JSF/HTML page.

Odisodium answered 16/5, 2011 at 11:10 Comment(2)
BalusC, I know this comment does not add any useful feedback but I just have to say it. You are a genius.Organicism
@arg20: Thank you :) Related answer btw: #6835999Odisodium
A
12

Maybe I misunderstand your question, but if by external css you just mean your own css that is not inline, then with JSF 2.0 you can use EL in your css as long as you include it with an <h:outputStylesheet>. For example, I have a project with this structure:

war
|__ WEB-INF
|   |__ *standardStuff*
|__ resources
|   |__ css
|   |   |__ style.css
|   |__ images
|       |__ image1.png
|__ xhtml
|   |__ index.xhtml

This is clearly not the complete file list, but should be enough to get the point. Then I have this in my index.xhtml:

<f:view xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets">
  <h:head/>
  <h:body>
    <h:outputStylesheet library="css" name="style.css" target="head"/>
    <ui:include src="content.xhtml"/>
  </h:body>
</f:view>

And in my css I have something like this:

.someClass {
    background-image: url('#{resource['images/image1.png']}');
}
Araiza answered 19/7, 2011 at 20:29 Comment(0)
O
10

I put the CSS images always in a subfolder of the CSS folder. E.g.

  • /resources/css/style.css
  • /resources/css/images/example.jpg

This way you just end up like

.someId { background-image:url(images/example.jpg); }

Yes, they are resolved relative to the URL of the CSS file itself, not to the main JSF/HTML page.

Odisodium answered 16/5, 2011 at 11:10 Comment(2)
BalusC, I know this comment does not add any useful feedback but I just have to say it. You are a genius.Organicism
@arg20: Thank you :) Related answer btw: #6835999Odisodium
V
7

You can use Expression Language (EL) along with the FacesContext to solve the issue. I use this technique frequently.

background-image: url('#{facesContext.externalContext.requestContextPath}/resources/images/background.gif');

This allows you to take advantage of JSF to provide dynamic content based on application input, or changes.

This technique works on JSF 1.2 and JSF 2.0

Viccora answered 9/8, 2011 at 13:33 Comment(0)
S
4

@Bozho's answer pretty much covers your options.

Another possibility is to continue having a static style sheet, and filling in the dynamic parts in the document's head where you have access to your expressions:

<head>

<!-- The style sheet contains 99% of the CSS ->
<link rel="stylesheet" href="static.css" type="text/css">

<!-- The remaining 1% is done here -->
<style type="text/css">
 .someClass { --- your dynamic values  here --- }
</style>

</head>

in the PHP world, this is the best practice because it saves an expensive PHP process from being created for the style sheet call. I don't know how things are in the JSP world but I assume it's similar.

Semicentennial answered 1/5, 2011 at 9:6 Comment(0)
D
3

No, you can't. You have several options:

  • hard-code absolute paths (domain relative, of course) - not that bad
  • use relative paths - can be a problem when you have nested urls like /view/external/foo/bar.jsf
  • preprocess them during build to set the proper paths
  • use a Filter (and both client and server-side caching) to set the proper paths.

(I feel I'm missing something)

Delilahdelimit answered 1/5, 2011 at 9:4 Comment(2)
How about a custom resource handler?Sennight
Please see my answer posted today. It was inserted somewhere on top which is a bit confusing to me o_OSennight
S
3

@Bozho: JSF allows to define a ResourceHandler to replace the standard one. You could just subclass javax.faces.application.ResourceHandler, handle specific requests and delegate others to the base class.

For the given example, the custom resource handler should determine the context and replace absolute path definitions. This enables dynamic path resolution on a per-request base.

Sennight answered 16/5, 2011 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.