BEM: Nested Blocks, what is the best approach? - bem

In the following markup, what is the best BEM approach?
This?:
<footer role="footer">
<footer class="footer__inner">
<div class="footer__left">© Some text</div>
<div class="footer__right">Some text</div>
</footer>
</footer>
OR this?:
<footer role="footer">
<footer class="footer__inner">
<div class="footer__inner__footer__left">© Some text</div>
<div class="footer__inner__footer__right">Some text</div>
</footer>
</footer>
Or none of them are right and you know a better way?
Thanks

You want to have clean reusable blocks. Ask yourself which part you might want to reuse.
Multi level nesting of blocks are frowned upon. And that's for a good reason. In case of reusability there should only be one block as root reference. Everything below that one block is, from a bem syntactic point of view, simply an element of that block. Not a sub-block, not a sub element, but only an element.
So, BEM doesn't care about your HTML structure. It's much more a question of what purpose a block or an element has.
I can't really tell from your example what the purpose of your nested footers might be, but it looks to me as if you consider the role attribute of your outer footer element as part of BEM-naming. But it's not. Keep in mind the idea of separation of concerns. role="footer" is HTML semantic. You should not use it as BEM naming reference because you might want to change that HTML attribute one day and then your BEM semantic would go up in smoke.
So, here's what I would do.
Let's say you want your outer footer to be the reusable element then you might want to name your classes like this (just as an example):
<footer class="footer" role="footer">
<footer class="footer__textbox">
<div class="footer__text footer__text--left"> <!-- left as modifier -->
<div class="footer__text footer__text--right"> <!-- right as modifier -->
</footer>
</footer>
Now you can take your footer and use it in any appropriate section of the page and anyone reading your code can get grasp an idea about the purpose of this css structure.

First variant looks fine for me.
Second is wrong as you shouldn't reflect DOM structure in class names. See https://en.bem.info/methodology/faq/#why-does-bem-not-recommend-using-elements-within-elements-block__elem1__elem2
Markup suggest by LongHike is also good.

Related

Conditionally closing tag in Thymeleaf

I need to conditionally close tag in my Thymeleaf template. Say, during iterating some collection of elements I have to wrap series of some of them into single <div>:
<div>...element1, element2, element3...</div>
<div>...element4...</div>
<div>...element5, element6...</div>
This could be archived if some way of conditionally tag closing would exist. But I can't obviously write </div th:if="...">. If it would be jsp I could easily write something like:
<%if (condition) {%></div><%}%>
Any ideas how to solve this issue?
EDIT To be precise, my elements aren't just strings, they are complex inner html blocks.
I think it's better represent the data as separate lists, as you mentioned in your previous answer.
But even for curiosity, there is an ugly workaround to achieve something similar to <%if (condition) {%></div><%}%>, as you asked.
The trick is to generate the tag as escaped text:
<th:block th:if="${openTagCondition}" th:utext="'<div>'" />
<th:block th:if="${colseTagCondition}" th:utext="'</div>'" />
This is just out of curiosity. I do not recommend using this workaround as it's pretty unreadable, harms maintainability and you can leave unbalanced tags.
I've found the workaround. Series of blocks which should be wrapped into single <div> should be represented as separated lists inside model. Say, it I have Element class which describes my element block. So, my model should be like:
List<Element> elementGroups
and I have to create double loop for it:
<div th:each="group : ${elementGroups}">
<th:block th:each="element : ${group}">
...
</th:block>
</div>
move the conditional logic up one layer
<body th:each="...">
<div></div>
</body>
take a look at the documentation here: http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#using-theach

how to loop images by names and numbers?

<div>
<a><img src="../photos/vacances01.jpg"></a>
</div>
<div>
<a><img src="../photos/vacances02.jpg"></a>
</div>
i would like to create a loop to read all the images in the file called vacances01, vacances02...
and famille01, famille02...
with for exemple the possibility to defina a part the word "vacances", or "famille", or "cars"....
like i specify a word which go after '../photos/' then it loops the numbers with 'i++' and it write at the end '.jpg'
and it generate that in loops :
<div>
<a><img src="../photos/vacances01.jpg"></a>
</div>
...
do you understand me ?
thank you in advance, my level is not very high
First of you have to understand that HTML is not a programming language in the way you think it is. HTML is, as the name suggests, a markup lanuage, used for designing websites. The "i++" is used in languages like C++ and Java. JavaScript could be used for such a task. How, I do not know.

Laravel blade templating discrepancy

I have main layout template /views/web/main_lo.blade.php as
<html>
<head>
<meta charset="UTF-8">
<title>{{$title or 'Default Title'}}</title>
</head>
<body>
<div class="section-1-outer">
#section('section-1')
<div class="section-1-parent">parent section 1</div>
#show
</div>
<div class="section-2-outer">
#section('section-2')
<div class="section-2-parent">parent section 2</div>
#show
</div>
<div class="section-3-outer">
#section('section-3')
<div class="section-3-parent">parent section 3</div>
#show
</div>
<div>
#yield('content')
</div>
</body>
</html>
and a section template as:
#extends('web.main_lo')
#section('section-1')
#parent
<div class='section-1-child'>
<p>Appended to parent</p>
</div>
#stop
#section('section-2')
<div class='section-2-child'>
<p>Replace parent</p>
</div>
#stop
#section('section-3')
<div class='section-3-child'>
<p>Replace parent</p>
</div>
#overwrite
Now here section layout is extending main_lo, here First section-1 which is quite clear that child section will include parent section-1 and content in parent section will also be printed.
Now my confusion is what on earth is difference between section-2 and section-3 implementation as they both replace content of parent section and only content in child get printed. I mean what is need of this extra #overwrite tag when documentation clearly states that
"Note that views which extend a Blade layout simply override sections
from the layout."
and then there is Overwriting Sections using #overwrite which is also for replacing content of parent section.
Laravel view's sections are a bit oddish and the bad part is that it's not obvious from the start.
Sections are actually extending in converse order, the section defined first will be the child and the one later will be the parent. So #parent is actually including the content of the section which may come after.
This is why I think parent and child are not the best terms for this system.
This is not obvious because of the conventional use case - layouts - it looks like the layout sections are the ones defined first. But actually they ran after the content sections are rendered.
This means #overwrite is actually used with the parent section, not the child. Which wouldn't make much sense in your example as you're yielding (#show) in the layout too, meaning you don't want to overwrite there.
The reason for this is actually because #overwrite was made for less conventional use cases, not when you have a layout-content, parent-child relationship.
Most often this happens when you include some partial files - maybe all over the place - where you use the same section names and you run into a problem when the earlier defined section is the one showing instead of the later.

For navigation, should figure titles go inside figcaption?

Consider that you land on a category webpage, whose sole purpose it is to direct you to the appropriate sub-category by informing you what's inside each with an image and a short title.
When it comes to UX considerations — it was suggested that the following arrangement would be the most optimal (text before image):
Each photo and text combination would link to the respective sub-category.
Considering semantic HTML5, since these are titles of sub-categories and not exactly captions, would it be appropriate to use the <figcaption> element? Or is something else?
Using figure captions:
<h2>Our Planet's Animals</h2>
<p>Contrary to popular belief...</p>
<figure>
<a>
<figcaption>Rhinos</figcaption>
<img />
</a>
</figure>
Using headers (or something else) instead:
<h2>Our Planet's Animals</h2>
<p>Contrary to popular belief...</p>
<figure>
<a>
<h3>Rhinos</h3>
<img />
</a>
</figure>
Or, what lese would be correct semantically, and allow ease of styling?
I think the use of the figure element would not be correct here, as this content is probably the main content of the page, but for figure it says:
[…] but that could, without affecting the flow of the document, be moved away from that primary content […]
You'd use figure if you have a diagram in a paper or a photograph in a news article etc.: content that "[…] is typically referenced as a single unit from the main flow of the document".
Instead, I'd use section for each category and enclose all categories in a nav (because it is the main navigation for that sectioning content, which is opened by the heading "Our Planet's Animals").
<h2>Our Planet's Animals</h2>
<p>Contrary to popular belief...</p>
<nav> <!-- nav could be omitted -->
<section>
<a>
<h1>Rhinos</h1> <!-- you could use h3 here instead -->
<img />
</a>
</section>
<section>
…
</section>
<section>
…
</section>
<section>
…
</section>
</nav>
If you don't want to use headings, one could also use a list for the categories (dl or ul). I think the ul fits better than dl here:
<h2>Our Planet's Animals</h2>
<p>Contrary to popular belief...</p>
<nav> <!-- nav could be omitted -->
<ul>
<li><a>Rhinos <img /></a></li>
<li>…</li>
<li>…</li>
<li>…</li>
</ul>
</nav>
It might also be possible to use section in each li element (<li><section>…</section></li>), but I'm not sure how this would affect the document outline.

What is ColdFusion Model Glue's equivalent to ASP.NET MVC 3's #section?

In ASP.NET MVC 3, you can have an #section within a view:
#section SideBar {
<p>Some content</p>
<p>Some more content</p>
}
<p>Body content</p>
Then in the master view, you would use this to render it:
<div id="sidebar">
#RenderSection("SideBar", false)
</div>
#RenderBody()
What would be the ColdFusion equivalent of this in the Model Glue framework? I know I can set simple variables in the view:
<cfset event.setValue("section", "Tables")>
Then use them in the master template like so:
<cfif event.exists("section")><h3>#event.getValue("section")#</h3></cfif>
But this only works well for one-liners and simple strings. What I'd like to do is include an entire HTML block. What is the best way of accomplishing this? I think this would work in theory:
<cfsavecontent variable="sidebar">
<p>Some content</p>
<p>Some more content</p>
</cfsavecontent>
<cfset event.setValue("sidebar", sidebar)>
But I was wondering if there's a better way of doing it.
Edit:
In response to Adam Cameron's answer, Model Glue, from what I can tell, only supports the ability to combine separate files into one template:
SideBar.cfm:
<p>Some content</p>
<p>Some more content</p>
Page.cfm:
<p>Body content</p>
ModelGlue.xml:
<event-handler name="page.text">
<views>
<include name="sidebar" template="SideBar.cfm"/>
<include name="body" template="Page.cfm"/>
<include name="main" template="main.cfm"/>
</views>
</event-handler>
main.cfm:
<cfoutput>#viewCollection.getView("sidebar")#</cfoutput>
<cfoutput>#viewCollection.getView("body")#</cfoutput>
I need to be able to declare the sidebar content within the page.cfm view. The thought here is that there will be a div somewhere in the main template that allows for a small HTML snippet, say an image with a text description and a link, which any view can populate. It wouldn't make sense to have something like Page1.cfm and Page1SidebarContent.cfm, Page2.cfm and Page2SidebarContent.cfm, etc...
ModelGlue doesn't support what you want to do out of the box. However its easy enough to achieve using Peter's suggestion and ModelGlue helpers for encapsulation.
Create a new cfc, call it PageFragment.cfc and drop it in to your ModelGlue helpers directory.
// untested!
component name="PageFragment" {
public boolean function exists(string name) {
return structkeyexists(request.subcontent, arguments.name);
}
public string function get(string name) {
if(exists(arguments.name)) return request.subcontent[arguments.name];
return "";
}
public void function set(string name, string value) {
request.subcontent[arguments.name] = arguments.value;
}
}
Then in your views you can do
index.cfm
<cfset helpers.PageFragment.set("sidebar", "<p>My sidebar content</p>") />
main.cfm
<cfif helpers.PageFragment.exists("sidebar")>
<div id="sidebar">#helpers.PageFragment.get("sidebar")#</div>
</cfif>
To avoid having to cfsavecontent all your fragments you could create a customtag that used thistag.generatedcontent and the caller scope to access your helpers.
By using helpers to encapsulate the functionality its really easy to reuse, or to change later without altering your views, for example you may want to add caching.
(Unfortunately) I haven't touched MG for ages, but I just googled the docs, as a reminder.
You need to read up on how views work, but this page of the docs summarises it succinctly:
http://docs.model-glue.com/wiki/ReferenceMaterials/ViewApi#ViewAPI
Specifically this code snippet:
<cfoutput>#viewcollection.getView("body")#</cfoutput>
It's probably a case of reading through the docs a bit, and reminding yourself about how model glue's implementation of MVC (specifically the V part, in your case!) works.
I haven't used Model-Glue nor ASP.NET MVC, but it seems what you want can be achieved like this:
In page.cfm do:
<cfsavecontent variable="Request.SubContent['ThisPage'].Sidebar">
<p>Some content</p>
<p>Some more content</p>
</cfsavecontent>
<p>Body content</p>
Then in main.cfm use:
<div id="sidebar">
<cfif StructKeyExists(Request.SubContent,PageName)
AND StructKeyExists(Request.SubContent[PageName],'Sidebar')
>
#Request.SubContent[PageName].Sidebar#
<cfelse>
#viewCollection.getView("default_sidebar")#
</cfif>
</div>
<cfoutput>#viewCollection.getView("body")#</cfoutput>
Depending on how things are structured, you might prefer to cache content in a persistent scope and/or hide it behind a couple of methods (possibly even extending Model-Glue to allow this natively; it is Open Source after all), but hopefully this gives a general idea?
I see what you mean now. I'm not sure MG will have that sort of functionality built-in because in an MVC environment, it's not really up to a view to be doing this sort of thing: you're kinda coupling controller & model stuff together in a view file. There might be a good reason for you doing this, but I wonder if it's your approach that might be your undoing here? Can you not put the "get the sidebar" stuff into the controller & have that call a model, and add in a sidebar view if needed? That'd be how I'd approach this.
That said, I know it's unhelpful having people say "I'm not going to answer your question, I'm just going to complain about it", so I'll have a look-see around and see if I can come up with something.
However given you're wanting to break-out of a MVC approach here, perhaps don't try to get MG to do this for you, just do what Peter suggests and capture a variable in the page.cfm view, stick it in a sensibly-structured struct (nice tautology, Cameron), and then look for it in the view you want to render it.

Resources