Problem/Motivation
Each field that comes out of care has a head load of templates coming out - some of them are usefull , where others are overkill. We can do better & make it easier for a themer to add the classes thats needed without loosing the flexibility.
now a field is wrapped in something like this:
<div class="field field-node--body field-name-body field-type-text-with-summary field-label-hidden edit-processed edit-field" data-edit-field-id="node/1/body/en/teaser">
<div class="field-items">
<div class="field-item">
<p>lorem...</p>
</div>
</div>
</div>
Thats 4 classes to describe the field & one to tell us what happens with the label.
.field
a class to tell us its a field - well thats great drupal but what should i use that for ?
If a themer wants to add this field it can be added easy to the field.twig.html file (see the example later)
.field-node--body
a class that its a specific type of field (body) in a node (vs a user ?)
Is this a thing anybody is actually gonna do - Atm we allready have a class wrapper around the element that tells us if this is a node / user etc.
We could remove this as well to be easy to add to the field wrapper in the template.
.field-name-body
a class that tells us what the specific name for this field.
Very usabable.
.field-type-text-with-summary
A class that tells us the "widget"
.field-label-hidden
a class to tell us where the label is placed in the wrapper
Proposed resolution
As basic wrappers that have very few default classes, it makes it easy and simple.
.field-{{ name }}
The unique name for the field, make sense to target that individually.
field-type-{{ fieldtype }}
The name for that fieldtype, makes it easy to work with common elements
.field-label-{{ label-position }}
The field label have a ui controller its not the role of this issue to do anything about that - if somebody wants to do that open up a seprate issue, adding it to the wrapper makes it easy for a themer to control the whole field.
the class dont exist if theres not a label added from the ui
This will make the markup very readable & still highly customizable.
If the themer needs more specifix classes they can easy be added to the classe for the field.
{{ fieldtype }}
{{ multiplevalues }}
{{ viewmode }}
{{ formatter }}
css quick examples
grap all the fields and add a border:
div[class="field-*"]{
border-bottom:1px solid pink
}
change the label behaviour
.field-label-inline .field-label{ display:inline-block }
.field-label-above .field-label{ display:block }
variations for a node vs a user:
.node-viewmode .field-{{ name }}{ ... }
.user-viewmode .field-{{ name }}{ ... }
field.twig
<div class="field-{{ name }} field-type-{{ fieldtype }} .field-label-{{ label-position }} {{ attributes.class }}" {{ attributes }}>
....
</div>
<div class="look-ma-no-hands-{{ field-formatter }} field-{{ name }} field-type-{{ fieldtype }} .field-label-{{ label-position }} {{ attributes.class }}" {{ attributes }}>
....
</div>
Remaining tasks
* Remove the classes - test if it actually breaks anything
* move the classes from the prepocess to a generic field.twig.html
* benchmark that it dosnt get slower
* enjoy less classes & easier for the themer to work in it
Comments
Comment #1
SweetchuckI think the "field type" and the "field widget" is not the same thing. So the example above is not correct.
And I think the kind of the "field widget" is not relevant when theming the output.
Comment #2
pdureau CreditAttribution: pdureau commentedIMO, we need in the view modes :
We can remove .field and .field-{{entitytype}}--{{fieldname}}, for the reasons you gave.
Field Widgets belong to the form modes, no to the view modes.
Comment #3
xandeadx CreditAttribution: xandeadx commentedI use only one class — field-name (ex: body, field-image). Other add as needed.
Comment #4
andypostComment #5
barraponto CreditAttribution: barraponto commentedAgreed, BUT
div[class="field-*"]
doesn't work. Also,.field
doesn't hurt (although I have never used it).Comment #6
mortendk CreditAttribution: mortendk commentedComment #7
mortendk CreditAttribution: mortendk commentedadding classes because it dosnt hurt is how we ended up with a ton of classes for each field - div[class*="field-"]{...} works so its corrected now.
is there a usecase for adding a Fieldformatter as a class ?
Comment #8
andypostSuppose formatter plugin ID makes sense, at least as prefixed somehow.
Entity reference fields are widely used in D8 and its 4 core formatters needs ability to be styled
Comment #9
mortendk CreditAttribution: mortendk commentedupdate of classnames in description with psedu code examples
Comment #10
LewisNymanAs far as I understand the CSS standards; we should only use two hyphens there is an original component that is being modified. For example
field-{{ name }}
would only make sense if there is afield
class. If there is no CSS being shared between the different variations then we can just use single hyphens.Comment #11
pdureau CreditAttribution: pdureau commentedIMHO, it is more the field formatter we want to style than the field itself or the field type. We don't usually do that because the field formatter class is missing.
The field name is too narrow because its is too specific (many differents fields with the same style to set) and linked to the data model.
The field type is too wide because there could be plenty of very different formatters for only one field type (the 4 core formatters of entity reference, as andypost told us)
Comment #12
mortendk CreditAttribution: mortendk commentedcan you add a couple of examples of the fieldformatter classes
Im trying to figure out a way that we can add in the least amount of classes from the beginnig but then make it exremely simple for the themer to add in classes as they are needed
Comment #13
sirviejo CreditAttribution: sirviejo commented+1 to this proposal.
Why:
- The actual situation of a huge amount of classes and the "dividitis" is an overkill, i understand this adds flexibility to properly target specific elements with our style. But when you compare the output of drupal with the output of the markup outputted by other major CMSs, ours is a lot more complex.
- This will make our DOM more lite. And as we are moving to a sort of mobile first approach, this will be a major boost.
Considerations:
- There could be a lot of modules depending on this markup, we need to chase those, and see how they will be affected by this changes. (Maybe we can create a module to revert this changes, to actual output)
Conclusion:
- Less is MORE
- Themers with specific needs, still be able to override within their own themes.
Comment #14
andypost@sirviejo Please provide an examples of "other cms markup", seems we need to investigate here more...
Comment #15
rteijeiro CreditAttribution: rteijeiro commentedChanged title. Everybody knows that "Durpal" is better :P
Comment #16
sirviejo CreditAttribution: sirviejo commented@andypost Let me grab you some examples and i will post them here
Comment #17
mortendk CreditAttribution: mortendk commentedLadies gentleman Can we please keep this to the wrapper classes We dont want this issue to be a monolith path, the divitis issue is here: #2214241 so please take that discussion there, about markup & whatever other cms'es do ;)
This is Drupal Core so yes - whatever we decide here will effect how a lot of contrib modules will have to change their code - look at me wheep ;)
We are making radical changes to the whole of core anyways so lets make it epic for the themers as well.
Usecases
What we need is realistic user case so we hit the 80% of the need NOT 100% out of the box.
and at the same time make sure its easy to add the very specific variations can be created in the theme.
what i would like to se was the classname printed directly into the template & with an attributes.class in the end, so if a module need a specific class to work its can be added that way.
so the template file would look like this
class="{{ field-name }} {{ field-type}} {{field-label-position}} {{attributes.class }}"
(in the field.html.twig file)
if the themer then have other variables ready for what might be needed later like {{ field-formatter }} {{field-viewmode }} etc.
Then its easy to figure out wtf is going on in the field.twig file. it a themer wants more classes added to ALL the fields, its easy to add em (but that need should not pester the rest of the 2% of the web)
Comment #18
LewisNymanI'm happy with these proposals.
.field
,field-node--body
, and.field-type-text-with-summary
are rarely useful. I'm not sure I've ever used them personally.Comment #19
barraponto CreditAttribution: barraponto commentedUpon discussing with @rteijeiro and @mortendk on IRC, we found that the only way to target every field without
.field
would bediv[class^='field-'],div[class*=' field-']
. It means targeting node entities within fields (rendered entity formatter) would bediv[class^='field-'] .node, div[class*=' field-'] .node
. Awful, any sane CSS dev would add the.field
selector back. This is an imagined example, though. I'd like to check if contributed themes in D7-land use.field
before taking it out.As for
.field-{{entity-type}}-{{field-name}}
, I think it's redundant since fields usually come inside the context of the rendered entity (meaning.{{entity-type}} .{{field-name}}
would be enough). I can only imagine Views adding fields outside of the entity context (and I would not be opposed to Views' preprocess adding this selector back in).Finally, I think
.field-{{widget-name}}
should only be added to entity forms, whilefield-{{formatter-name}}
should only be added to rendered entities.Comment #20
mortendk CreditAttribution: mortendk commented@barraponto
So can you explain what exactly you want & need .field class ?
it would be really great if there could be a good real world example of this , not a "this is how we always have done it"
Can i get a comment of the idea of removing all these predefined classes from a preprocess and putting it directly in to the template file, thats where the goal is here. (listed again in #17) - still keepin a modules ability to add in needed classes with {{ attributes.class }}
this is not about finding the 100% solutions to all problems, this is about finding a good solutions that themers can work with, without having to dig into drupals inner workings (aka php n stuff)
Comment #21
mortendk CreditAttribution: mortendk commentedComment #22
LewisNymanSplit deciding the classes and moving the classes into the twig template in #2217731: Move field classes out of preprocess and into templates
Comment #23
mortendk CreditAttribution: mortendk commented+1 this can turn into epic bikeshed
Comment #24
derheap CreditAttribution: derheap commentedJust to provide some quick data:
find core -name "*.css" | xargs grep -R "\.field"
Lists all css rules with .field in core:
I have not much time right to to investigate further, but to me is obvious:
* .field is only used 2-3 times, and mostly in admin.
* most field- classes are extra classes for admin, we can inject them with {{attributes.class}}
So I am +1 for #17:
class="{{ field-name }} {{ field-type}} {{field-label-position}} {{attributes.class }}"
And I would reduce it in the normal field.html.twig to :
class="{{field-label-position}} {{attributes.class }}"
And provide the others (
{{ field-name }} {{ field-type}}
) as examples in field.html.twigThe Admin-Theme (Seven) can redefine field.html.twig or inject the classes in preprocess.
Keep it to the bare minimum in standard markup.
Comment #25
star-szrTagging for focus.
Comment #26
LewisNymanComment #27
lauriiiComment #28
lauriiiComment #29
andypostComment #30
star-szrBump, anything need to be done here now that we have Classy and also #2214241: Field default markup - removing the divitis?
Comment #31
mortendk CreditAttribution: mortendk as a volunteer commentedwhat we should do was look into what we really want of classes wrapping and se how many we can remove out of the system
Comment #32
mortendk CreditAttribution: mortendk as a volunteer commentedPersonally i would like to cook the classes down a little bit - First of all its really really really easy to add in classes as they are needed, so we should not be to afraid of cleaning up even more imho.
now a field is written like this
field field--name-[name] field--type-[type] field--label-hidden field__item"
if we look at a field as a "componen" - then it should be based on what kind of widget it is, so a theme would actually not use the name but use the kind of widget to write the css around:
1:
field
cause .field really ?2:
field--name-[name]
the name is very specific to the single field3:
field--label-hidden
afaik we dont really need this, we have it inside of the label so the wrapper dont really need itfield--type-[type]
this is where the gold is.field__item
to keep with the bemmaybe its to late to push this in right now ?
Comment #33
joelpittet@mortendk wrote this:
at BADCamp 2015
Triage theme system. If there is further class cleanup it may have to be done in D9 at this point.