Dynamic CSS with a variable parameter? (is it possible?) - css

I'm trying to create a menu system, which is dynamically resizes itself horizontally to fill out depending on how many "li" entries there are, I'm dynamically creating the webpages with XSLT. My thoughts are whether this is possible todo within CSS?
Here's my CSS specifically for the HTML page
nav[role="navigation"] li {
float: left;
width: 10.00%; /* I want to dynamically set this width */
}
Snippet of HTML in question
<nav role="navigation" count="2"><?xml version="1.0" encoding="utf-8"?>
<ul>
<li>
Movies
</li>
<li>
News
</li>
<ul>
</nav>
My thoughts are of whether something like this would be possible to call the CSS with a parameter, or am I going against it's declarative ways?;
nav[role="navigation"] li param {
float: left;
switch(param)
{
case : 5
{
width: 20.00%;
}
case : 3
{
width: 33.33333%;
}
}
}

CSS is not a programming language. CSS3 has a bit of logic here or there, but no switch().
For your purposes, the simplest solution by far is a touch of javascript, supplied here assuming that you use jQuery:
var $navLis = $('nav[role=navigation] > ul > *');
$navLis.addClass('count'+$navLis.length); // add a class to every li indicating
// total number of list items
Then in your CSS:
nav[role=navigation] li { /* default styling & width */ }
nav[role=navigation] li.count2 { /* your conditional styling */ }
nav[role=navigation] li.count5 { /* your conditional styling */ }
/* etc */
or just set the width directly with jQuery:
$navLis.style('width', (100/$navLis.length)+'%');
If you demand pure CSS, then get out your logic hat and look over the CSS3 selectors specification. You can construct some Byzantine and rather brittle CSS code to fake logic, such as the following selector.
nav[role=navigation] li:first-child + nav[role=navigation] li:last-child {
/* matches last of two items if a list has only two items */
}
If you're using a CMS that knows how many items it is going to be putting in the list, then you can get fancy on your server backend by adding little bits of PHP to your CSS:
<?php header('Content-type: text/css');
if (isset($_GET['navcount']) && $_GET['navcount'] != "") {
$navcount = $_GET['navcount'];
} else { $navcount = 5.0; } // Default value
?>
/* ... your css code here... */
nav[role="navigation"] li {
float: left;
width: <?php echo (100.0/$navcount); ?>%;
}
Then you request the CSS/PHP script like this from your HTML:
<link rel="stylesheet" type="text/css" href="/path/to/style.php?navcount=5" />
There's a few great tools out there for writing stylesheets that mix down nicely into CSS, and some even provide PHP implementations to do so dynamically. The strongest CSS extension right now is Sass, which has just the sort of syntax that you're looking for. I'd recommend using Sass through Compass, which is a framework for Sass that really gives it some teeth. You can parse Sass into CSS on-the-fly in PHP using phamlp
Although Compass (and Sass) are awesome tools, plugging them into an existing project could be more trouble than its worth. You might just want to do simple logic using Javascript.

have you tried LESS?
LESS extends CSS with dynamic behavior
such as variables, mixins, operations
and functions. LESS runs on both the
client-side (IE 6+, Webkit, Firefox)
and server-side, with Node.js.

It is not possible with simple CSS.
But for this specific example, you might look at the display: table-cell; property.

Related

How to think about styling AngularJS components?

I'm working on an AngularJS project with the aim of slowly getting things in order for Angular 6, or whatever version is out when we start on the upgrade. One of the big pieces of that work is converting existing directives into components.
The thing I'm struggling the most with, is that every instance of a component introduces an extra element into the DOM that wraps my actual component HTML and breaks the hierarchy, making it very hard to write CSS that does what it needs to.
To illustrate my dilemma, imagine a simple component called alert that provides styling for various types of messages you want a user to pay attention to. It accepts two bindings, a message and a type. Depending on the type we will add some special styling, and maybe display a different icon. All of the display logic should be encapsulated within the component, so the person using it just has to make sure they are passing the data correctly and it will work.
<alert message="someCtrl.someVal" type="someCtrl.someVal"></alert>
Option A: put styling on a <div> inside the extra element
Component template
<div
class="alert"
ng-class="{'alert--success': alert.type === 'success', 'alert--error': alert.type === 'error'}">
<div class="alert__message">{{alert.message}}</div>
<a class="alert__close" ng-click="alert.close()">
</div>
Sass
.alert {
& + & {
margin-top: 1rem; // this will be ignored
}
&--success {
background-color: green; // this will work
}
&--error {
background-color: red; // this will work
}
}
This works fine as long as the component is completely ignorant of everything around it, but the second you want to put it inside a flex-parent, or use a selector like "+", it breaks.
Option B: try to style the extra element directly
Component template
<div class="alert__message">{{alert.message}}</div>
<a class="alert__close" ng-click="alert.close()">
Sass
alert {
& + & {
margin-top: 1rem; // this will work now
}
.alert--success {
background-color: green; // nowhere to put this
}
.alert--error {
background-color: red; // nowhere to put this
}
}
Now I have the opposite problem, because I have nowhere to attach my modifier classes for the success and error states.
Am I missing something here? What's the best way to handle the presence of this additional element which sits above the scope of the component itself?
I personally do option A. This allows you to easily identify and create specific styles for your components without fear that they will overwrite site-wide styles. For instance, I'll use nested styles to accomplish this:
#componentContainer {
input[type=text] {
background-color: red;
}
}
This will allow you to make generic styles for your component that won't spill out into the rest of your solution.

CSS Modules & ReactJS: Parent and child CSS classes in different components

So I am building a react application and have a quick question. If I have two separate components:
and
with CSS classes navigation.css and navigationLogo.css respectively. In navigation.css I have a class named .main and in navigationLogo.css I want to have a class like so:
.main .main_in_logo {
color: red;
}
But with CSS Modules I am unable to do this, any ideas on a work around?
I just feel that the explanations here are not complete enough. In css you do .parentSelector .childSelector in order to select the child. The same rule is for css modules, but in your html/jsx you should add to the parent and the child the relevant className -> styles.parentSelector , styles.childSelector.
<div className={styles.container}>text</div>
This way you can have in your css something like:
.banner .container{
background-color:reb;
}
.banner .container{
background-color:blue;
}
Sometimes you use libraries and you want to change something somewhere down the DOM inside the library and you can't change its source code. In this case you can use the :global like this:
.parentElement :global(div)
.parentElement :global(#some-lib-element-selector)
I was looking for the same problem and didn't find the solution here, maybe because the post is 3 years old. The accepted answer is, in my opinion but not mine only, not scalable.
I don't really know if this is something new, but I found out what I would do in vanilla CSS adapted to CSS modules.
Here is what I did and fully suits my needs:
/* parent.css */
.main {
...some CSS...
}
/* logo.css */
#value main from "./parent.css";
.logo {
...some CSS...
}
.main .logo {
color: red
}
Here, we are using #value, which is a CSS modules variable and allows us to bind with another file to build a selector including the final name of the parent "main".
As strange as it looks to me, it took some time to find out about this solution, I hope this will save some time and help other people!
Why you need to create .main .main_in_logo - the main idea of styles with parent elements its not to broke your css with other styles in the future. But its impossible with css modules, because your styles will be unique forever.
But even you really need it you can use global css for these 2 components - documentation about global css for react-css-modules.
The child component should not have a css rule that is dependent upon the parent css classname.
the child should just be:
.main_in_logo { color: red; }
If you need to define styles that involve both parent and child, then the easiest way is to define the styles completely in the parent:
/* navigation.css */
.main .main_in_logo {
color: red;
}
Then have the parent pass the css class to the child and tell the child to use it:
// Navigation.js
<NavigationLogo className={navigationCss.main_in_logo} />
// NavigationLogo.js
<div className={"foo " + this.props.className}>stuff</div>
You don't need to be specify which child class you are referring to when using CSS modules in ReactjS.
so doing:
.main_in_logo {
color: red;
}
will be enough in the stylesheet.
I ended up using CSS the normal way but with BEM convention.
I mean after all, what the CSS modules do is adding the [this_name].module.css to your css classes anyway. If you typed it correctly in the first place, there's no need of using this. It's just a new abstract that allow newbies so they can just do stuff without having to worry about class names clashing.
// Main.jsx
import './Main.css'
import Logo from './Logo.jsx'
const Main = () => {
return (
<div className="main">
<Logo className="main__logo" />
</div>
)
}
/* Main.css */
.main {/* do magic */}
.main__logo {/* do magic but for Logo component */}
So maybe you had Logo component like this..
// Logo.jsx
import './Logo.css'
const Logo = () => {
return (
<div className="logo">
<img className="logo__img" />
</div>
)
}
/* Logo.css */
.logo {/* do magic for logo */}
.logo__img {/* do magic for logo's image */}
This feels much more natural.

Is a good practice to combine multiple css classes when trying to create isolated components?

I've been using for some time a "BEM like" syntax in my projects. Recently, I was just re-reading some CSS articles when I saw this: https://en.bem.info/methodology/css/#single-responsibility-principle
Basically, instead of putting all the styles of header__button inside that class, it also relays on styles from button class. Aren't we in this case coupling the element of header with the button class? That means that if in the future, we're gonna change the button class, we also need to remember exactly where we're using this class.
In this example maybe it makes sense because you're trying to have the same styles, but what about a layout component? For instance, let's suppose that I have a Menu class that position some children vertically, and I have a Sidebar class that's also going to apply some style to those children. And we use them like this:
menu.css
Menu {
}
Menu__item {
}
sidebar.css
Sidebar {
}
Sidebar__item {
}
index.html
<div class="Menu Sidebar">
<div class="Menu__item Sidebar__item">
</div>
<div class="Menu__item Sidebar__item">
</div>
</div>
If we don't put all the code about how to position items in the Sidebar class and in the future we change some of this code from Menu, maybe the Sidebar class is going to be broken. In the other case, if we repeat code in both classes Menu and Sidebar we're violating the SRP (single responsibility principle) discussed at the begging of the question. That's what lately, in my projects, I've been favoring code duplication, so I would write all the code needed for a Sidebar into the Sidebar class.
But, what would be the best practice here?
There's also a chapter which partially answers your question: https://en.bem.info/methodology/css/#external-geometry-and-positioning
In your example I'd day Sidebar should be responsible for Menu positioning but it shouldn't know anything about Menu__items. And Menu in its turn should not know anything about its own positioning but should position its items inside.
If you really need to change something in Menu__item positioning when it's inside Sidebar use nested selectors:
.Menu {
}
.Menu__item {
}
.Sidebar {
}
.Sidebar .Menu__item {
}
I think, you should decide, what is it: menu or sidebar, and use one of these classes. If blocks are different a bit, you should use modifiers. If it is impossible to do this with modifiers, use two different classes.
Using modifiers:
// your menu
.menu { }
.menu__item { }
// your sidebar
.menu--some-modifier { }
.menu__item--some-modifier { }
//
.sidebar__menu {
// set some styles (margins, positioning) for .menu
}
Two independent different blocks:
// your menu
.menu { }
.menu__item { }
// your sidebar
.sidebar { }
.sidebar__item { }

LESS mixins vs classes

I'm looking into LESS because I definitely see some of their benefits. For instance colour declaration.
One thing I don't understand tho, and maybe I'm not getting the flow right is - why use the following LESS snippet
.radius {
-webkit-border-radius:5px;
-moz-border-radius:5px;
border-radius:5px;
}
.btn-red{
background-color:red;
.radius;
}
.btn-green{
background-color:green;
.radius;
}
...
When we can use the .radius class in the html file right away. I'm left with the impression that LESS will add a ton of duplicate code once it gets compiled.
I'm using the following, which makes more sense. Same with font-size, margins, etc... Aren't classes used in such cases?
<div class="btn-red radius">Cancel</div>
<div class="btn-green radius">Go</div>
The snippet above does not benefit from SASS/LESS capabilities that much. Lets have a closer look and check this SCSS snippet.
// Abstract placeholder.
%radius {
border-radius: 5px;
}
// Put your global styling here.
// I'm assuming that you can alter the markup and have button.btn.btn-green
.btn {
// Color modifier.
&-red {
#extend %radius;
background-color: red;
}
&-green {
#extend %radius;
background-color: green;
}
}
The CSS output will be:
.btn-red, .btn-green {
border-radius: 5px;
}
.btn-red {
background-color: red;
}
.btn-green {
background-color: green;
}
And then you have to pick up Autoprefixer and vendor-prefixes issue is solved once and for all.
Because now, you can just specify the class btn_red or btn_green and all the buttons will automatically have a radius.
Your HTML should contain only the semantics, and styling or classes referring to styling should not be part of it.
That applies to the other classes as well. If for instance, you would rename btn_red to btn_cancel, you have a meaningful classname that you can apply to any kind of cancel button. And in the CSS you can specify that a cancel button is red and a 'Go' button is green, and both have a radius, without needing to modify the HTML at all.
So, the ultimate goal is to have the HTML describe the structure and the CSS describe how that structure should look. And a CSS preprocessor is only their to make a bulky spaghetti-like CSS file more structured.
There are several benefits.
You can use more semantic class names. Rather than encoding style information directly in your class names, (btn-red, radius) you could use a single class that conveys the usage of the style, rather than its contents.
You can avoid repeating yourself.
#radius-size: 5px;
-webkit-border-radius:#radius-size;
-moz-border-radius:#radius-size;
border-radius:#radius-size;
You can parameterize it so that you'd be able to use different radiuses (radii?) in different contexts.
.radius(#radius-size) { ... }
Because there are cases that developer has-no-access or don't-want to change the markup. and the only solution is to include all props from a predefined class.
for example:
you have bootstrap loaded (then you already have .has-success and .has-error classes) and if you want to use HTML5's native form validation using input's :valid and :invalid states, you have to use JavaScript to add/remove success/error classes based on input's states. but with this feature of LESS you can include all props of success/error class inside input's states. the code for this example could be something like this:
#myinput {
&:valid { .has-success; }
&:invalid { .has-error; }
}

Inherit attributes from another object in css

I have a class in my css called .btn:
.btn {
//stuff here
}
and I am going to create another class, lets say .btn2. I want to be able to inherit the characteristics from .btn into btn2, as I only want to change the color of button 2. Is there a way in CSS for this? Or should I just copy and paste the original stuff into the new class?
I'd suggest:
/* comma-separated selectors: */
.btn,
.btn2 {
/* shared properties */
}
.btn2 {
/* properties unique to btn2 */
}
JS Fiddle demo.
You can do it with dynamic stylesheets. Check out LESS or SASS.
EDIT:
Some additional info at a commenter's request. Here are the official sites. They both have examples on their home pages.
http://lesscss.org/
http://sass-lang.com/
What you can do is this
.btn, .btn2 {
/* Styles goes here */
}
This way, both the classes will share common properties defined in the rule block.
As far as the inheritance goes, something you would like to have..
.btn2 {
.btn; /* Won't work in pure CSS */
}
Won't work in pure CSS, you need to take a look at SASS or LESS

Resources