theagilecoder

theagilecoder

Best practice of using custom CSS files in a project

As my Phoenix project has grown bigger, all the custom CSS for all the pages put in a single app.css file feels wierd and problematic. What is the best practice in this regard ? Is there any way I can use separate CSS files for separate pages in my Phoenix app ?

Marked As Solved

thojanssens1

thojanssens1

Use css imports?

/* app.css */

@import "./reset.css";
@import "./variables.css";
@import "./registration-page.css";
/* and so on */

Also Liked

lkuty

lkuty

I use render_existing/3 and for example I have for CSS:

<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
<%= render_existing(@view_module, "css." <> @view_template, assigns) %>
<%= if assigns[:live_view_module] do %>
<%= render_existing @live_view_module, "css", assigns %>
<% end %>

and for JS:

<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
<%= render_existing(@view_module, "js." <> @view_template, assigns) %>
<%= if assigns[:live_view_module] do %>
<%= render_existing @live_view_module, "js", assigns %>
<% end %>

In my PageView, I have code to provide links to CSS and JS:

  def render("css.last_all.html", %{conn: conn}) do
    href = Routes.static_path(conn, "/css/last_all.css")
    ~E(<link rel="stylesheet" href="<%=href%>" />)
  end
  def render("js.last_all.html", %{conn: conn}) do
    src = Routes.static_path(conn, "/js/last_all.js")
    ~E(<script type="text/javascript" src="<%=src%>"></script>)
  end

In my live views, I use customized links:

  def render("css", _assigns) do
    {:safe, "<link rel='stylesheet' href='/css/overview.css'/>"}
  end
  def render("js", _assigns) do
    {:safe, "<script type='text/javascript' src='/js/overview.js'></script>"}
  end

Thus, the layout calls functions to render (provide HTML link and script) CSS and JS. Note that webpack.config.js has to have an entry for every use case or the file won’t be available since they are not imported from app.js.

'overview': ['./js/overview.js'].concat(glob.sync('./vendor/**/*.js')),
'last_all': ['./js/last_all.js'].concat(glob.sync('./vendor/**/*.js')),
...
thojanssens1

thojanssens1

I use BEM class name conventions, so such conflicts don’t happen to me.

You can also use render_existing/3 in your layout template to include a CSS file per page.

lucaong

lucaong

This will be resolved according to the CSS cascading rules. It’s not something specific to Phoenix, it is about CSS in general.

In short, if you have two CSS rules that both could apply to an element:

  • The most specific one wins (e.g. if you have <span class="danger">...</span> and the CSS rules span.danger { color: red; } and span { color: black; }, the first would win because it is more specific (it targets and element and a class). Specificity is an important concept in CSS, worth a deeper look, as it has deeper ramifications than in this simple example.

  • If the two rules are equally specific, the one that appears last in the code wins, by overriding the previous one.

You can use specificity of rules at your advantage to apply style to some elements and not to others. BEM class naming is one such way.

Allow me to make a pledge to all web engineers to take the due time to learn CSS well :slight_smile: It is a truly amazing language, one of the pillars of the web, and too often disregarded as a secondary topic. Good mastery of CSS is a powerful skill to have in a developer’s toolbox.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; somethi...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

We're in Beta

About us Mission Statement