4
votes

I'm trying to include CSS in Phoenix templates (EEx) so that I can define components (that render on the server) that not only include HTML but also their own CSS. For that I would like to include a tag with the CSS for that template (component) hoping it would be injected in the <head> but that's not what happen. I made a few experiences and wasn't able to achieve that (weird enough when I did that my webpage didn't break and I could see <head> and <style> tags inside the <body>). A sample templateXYZ.html.eex code could be:

<style>
   .main {color: red;}
</style>

<div class="main">

    <!-- Html code goes here -->

</div>

Note that the main goal of this is to allow me to write all the "component" code in one template (Html, CSS and Javascript - with the later there's no problem so I'm omitting it in the example/question) in a way that I only need to place the template in the proper place inside my other templates (rendering a template inside another template is also not a problem) and do nothing more (like as when I have a separated CSS file and need to import it in the <head>).

As a comparison, I can do what I want in the client side with raw Javascript that places my <style> and HTML in the DOM like this:

function f_auxButton(imgpath,id){
        if (document.getElementById('auxButtonId')){} // <style> is only created on first component instanciation to avoid duplication
    else {
    $('<style id="auxButtonId">\
       .auxButton {\
            width: 25px;\
            height: 25px;\
            margin: 10px;\
        }\
    <\style>').appendTo("head")}

    return '<img src="'+imgpath+'" class="auxButton" id="'+id+'">'

Then I just have to call <script>f_auxButton(arg1,arg2)</script> where I want to place the HMTL and I get it (plus the <style> tag that goes into the <head>.

So, is there a way of doing this?

1
Hi Paulo do you have code you could share to help see what you're trying to accomplish? If it's just a matter of including css or javascript, etc. in a template by template basis one possible solution would be to create a shared directory that allowed you to render the shared templates e.g. /web/templates/shared/_styles.html.eex and then within that file you would add the necessary css but within the control flow you need. - Donovan Dikaio
I found this question: stackoverflow.com/questions/2830296/…. It gives me a work around, thus not the answer I'm looking for... - Paulo Janeiro
Hi Paulo. I understand what you mean now, I think. You would like to create one (shared template) file that you would embed in other templates that would then add that shared file html and css but the css being applied to the head and the html where you included the shared file. - Donovan Dikaio
html and css but the css being applied to the head and the html where you included the shared file. Unfortunately I'm also new to Phoenix/Elixir and not sure how to do that but you could also ask someone in the #irc-lang channel for help and if you find the solution post it back here. - Donovan Dikaio
@Dikaio Thank you. I'm going to try to figure this out and then I'll post it here. - Paulo Janeiro

1 Answers

1
votes

app.html.eex

<!doctype html>
<html>
    <head>
        <title></title>
        <%= render_existing view_module(@conn), "_styles.html", assigns %>
    </head>
    <body>
        <div class="main">
            <%= render_existing view_module(@conn), "_component.html", assigns %>
        </div>
    </body>
</html>

/web/templates/shared/_components.html.eex

<%= render MyApp.PageView, "_styles.html" %>
<img src="<%= static_path(MyApp.Endpoint, "/path/example.png")%>", class="auxButton">

/web/templates/page/_styles.html.eex

<style>
  .auxButton {width: 25px;height: 25px;margin: 10px;}
</style>

Final Result

<!doctype html>
  <html>
    <head>
      <title>My App</title>
      <style>
        .auxButton {width: 25px;height: 25px;margin: 10px;}
      </style>
    </head>
      <body>
        <div class="main">
          <img src="/path/example.png" class="auxButton">
        </div>
      </body>
   </html>