CSS3 - Color item based on certain condition - css

I have a table with a column "amount". If the item in the cell is positive I want it to be colored in green, if not in red.
This can be done very easily using jQuery but I wondered if there's any trick using new CSS3 features that could help me achieve this without using javascript at all.
Is this possible?

Perhaps you can arrange for the server to generate HTML with data-* attributes containing the value. Then:
<span data-value="-123">-123</span>
[data-value^="-"] {
color: red;
}
In words, "if the value of the data-value attribute starts with a minus sign, color the text red."
Another idea is to use the :invalid pseudo-class. This will only work for an input element, unfortunately. However, you can disable it to prevent input and style it so it looks like regular text. You will also have to arrange to have the value placed in the value attribute of the input element:
<!-- specify a pattern which permits only positive numbers -->
<input type="text" pattern="\\d*" value="-123" disabled>
input:invalid {
color: red;
}
Neither of these approaches is ideal; you'll probably end up using JS.

When you return the data for the table, you will need to add a class to the TD for your amount column for any value is less than 0. You could use "negative" and give this a style of colour:RED; You can set the default style for the amount column TD as green for all positive values, and when the browser encounters the "negative" style it will set negative values to be red.

Use something like this:
<style>
.positive
{
background:green;
}
.negative
{
background:red;
}
</style>
<script>
function colorBackground(){
if (document.getElementById('yourid').value < 0){
document.getElementById('yourid').style.bgColor = "red";
}else {
document.getElementById('yourid').style.bgColor = "green";
}
}
</script>

Apparently this can't be done using CSS3 only.
Here is the jQuery code I used in the end:
$( document ).ready(function() {
$(".amount").each(function() {
$(this).addClass($(this).text() >= 0 ? "positive" : "negative");
});
});
If anyone has any shorter version of it, I'd be happy to have it :)
Thanks

Related

ng-repeat values with conditional css

We have a json datasource populating an html page just fine. ng-style, ng-switch don't
appear to address our issue. We need to conditional apply on the fly css styling based
on the return value from ng-repeat. For example when the value returned from
{{mem.name}} is 'restricted' we need the background to show as yellow and the text colored black. When the value of {{mem.name}} is 'closed' we need the background to show as red and the text colored white. This has to happen based on the return value and not be based on any user interaction. Thank you in advance for any direction offered.
Try adding the below to the repeating element HTML:
ng-class="{{mem.name == 'restricted' && 'restrictedClass' || mem.name == 'closed' && 'closedClass'}}"
Then in your CSS
.restrictedClass{
background:yellow;
color:black;
}
.closedClass{
background:red;
white;
}

How do I conditionally apply CSS styles in AngularJS?

Q1. Suppose I want to alter the look of each "item" that a user marks for deletion before the main "delete" button is pressed. (This immediate visual feedback should eliminate the need for the proverbial "are you sure?" dialog box.) The user will check checkboxes to indicate which items should be deleted. If a checkbox is unchecked, that item should revert back to its normal look.
What's the best way to apply or remove the CSS styling?
Q2. Suppose I want to allow each user to personalize how my site is presented. E.g., select from a fixed set of font sizes, allow user-definable foreground and background colors, etc.
What's the best way to apply the CSS styling the user selects/inputs?
Angular provides a number of built-in directives for manipulating CSS styling conditionally/dynamically:
ng-class - use when the set of CSS styles is static/known ahead of time
ng-style - use when you can't define a CSS class because the style values may change dynamically. Think programmable control of the style values.
ng-show and ng-hide - use if you only need to show or hide something (modifies CSS)
ng-if - new in version 1.1.5, use instead of the more verbose ng-switch if you only need to check for a single condition (modifies DOM)
ng-switch - use instead of using several mutually exclusive ng-shows (modifies DOM)
ng-disabled and ng-readonly - use to restrict form element behavior
ng-animate - new in version 1.1.4, use to add CSS3 transitions/animations
The normal "Angular way" involves tying a model/scope property to a UI element that will accept user input/manipulation (i.e., use ng-model), and then associating that model property to one of the built-in directives mentioned above.
When the user changes the UI, Angular will automatically update the associated elements on the page.
Q1 sounds like a good case for ng-class -- the CSS styling can be captured in a class.
ng-class accepts an "expression" that must evaluate to one of the following:
a string of space-delimited class names
an array of class names
a map/object of class names to boolean values
Assuming your items are displayed using ng-repeat over some array model, and that when the checkbox for an item is checked you want to apply the pending-delete class:
<div ng-repeat="item in items" ng-class="{'pending-delete': item.checked}">
... HTML to display the item ...
<input type="checkbox" ng-model="item.checked">
</div>
Above, we used ng-class expression type #3 - a map/object of class names to boolean values.
Q2 sounds like a good case for ng-style -- the CSS styling is dynamic, so we can't define a class for this.
ng-style accepts an "expression" that must evaluate to:
an map/object of CSS style names to CSS values
For a contrived example, suppose the user can type in a color name into a texbox for the background color (a jQuery color picker would be much nicer):
<div class="main-body" ng-style="{color: myColor}">
...
<input type="text" ng-model="myColor" placeholder="enter a color name">
Fiddle for both of the above.
The fiddle also contains an example of ng-show and ng-hide. If a checkbox is checked, in addition to the background-color turning pink, some text is shown. If 'red' is entered in the textbox, a div becomes hidden.
I have found problems when applying classes inside table elements when I had one class already applied to the whole table (for example, a color applied to the odd rows <myClass tbody tr:nth-child(even) td>). It seems that when you inspect the element with Developer Tools, the element.style has no style assigned. So instead of using ng-class, I have tried using ng-style, and in this case, the new CSS attribute does appear inside element.style. This code works great for me:
<tr ng-repeat="element in collection">
[...amazing code...]
<td ng-style="myvar === 0 && {'background-color': 'red'} ||
myvar === 1 && {'background-color': 'green'} ||
myvar === 2 && {'background-color': 'yellow'}">{{ myvar }}</td>
[...more amazing code...]
</tr>
Myvar is what I am evaluating, and in each case I apply a style to each <td> depending on myvar value, that overwrites the current style applied by the CSS class for the whole table.
UPDATE
If you want to apply a class to the table for example, when visiting a page or in other cases, you can use this structure:
<li ng-class="{ active: isActive('/route_a') || isActive('/route_b')}">
Basically, what we need to activate a ng-class is the class to apply and a true or false statement. True applies the class and false doesn't. So here we have two checks of the route of the page and an OR between them, so if we are in /route_a OR we are in route_b, the active class will be applied.
This works just having a logic function on the right that returns true or false.
So in the first example, ng-style is conditioned by three statements. If all of them are false, no style is applied, but following our logic, at least one is going to be applied, so, the logic expression will check which variable comparison is true and because a non empty array is always true, that will left an array as return and with only one true, considering we are using OR for the whole response, the style remaining will be applied.
By the way, I forgot to give you the function isActive():
$rootScope.isActive = function(viewLocation) {
return viewLocation === $location.path();
};
NEW UPDATE
Here you have something I find really useful. When you need to apply a class depending on the value of a variable, for example, an icon depending on the contents of the div, you can use the following code (very useful in ng-repeat):
<i class="fa" ng-class="{ 'fa-github' : type === 0,
'fa-linkedin' : type === 1,
'fa-skype' : type === 2,
'fa-google' : type === 3 }"></i>
Icons from Font Awesome
This works well when ng-class can't be used (for example when styling SVG):
ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"
(I think you need to be on latest unstable Angular to use ng-attr-, I'm currently on 1.1.4)
I have published an article on working with AngularJS+SVG. It talks about this issue and numerous others. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS
span class="circle circle-{{selectcss(document.Extension)}}">
and code
$scope.selectcss = function (data) {
if (data == '.pdf')
return 'circle circle-pdf';
else
return 'circle circle-small';
};
css
.circle-pdf {
width: 24px;
height: 24px;
font-size: 16px;
font-weight: 700;
padding-top: 3px;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
background-image: url(images/pdf_icon32.png);
}
This solution did the trick for me
<a ng-style="{true: {paddingLeft: '25px'}, false: {}}[deleteTriggered]">...</a>
You can use ternary expression. There are two ways to do this:
<div ng-style="myVariable > 100 ? {'color': 'red'} : {'color': 'blue'}"></div>
or...
<div ng-style="{'color': (myVariable > 100) ? 'red' : 'blue' }"></div>
Another option when you need a simple css style of one or two properties:
View:
<tr ng-repeat="element in collection">
[...amazing code...]
<td ng-style="{'background-color': getTrColor(element.myvar)}">
{{ element.myvar }}
</td>
[...more amazing code...]
</tr>
Controller:
$scope.getTrColor = function (colorIndex) {
switch(colorIndex){
case 0: return 'red';
case 1: return 'green';
default: return 'yellow';
}
};
See the following example
<!DOCTYPE html>
<html ng-app>
<head>
<title>Demo Changing CSS Classes Conditionally with Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="res/js/controllers.js"></script>
<style>
.checkboxList {
border:1px solid #000;
background-color:#fff;
color:#000;
width:300px;
height: 100px;
overflow-y: scroll;
}
.uncheckedClass {
background-color:#eeeeee;
color:black;
}
.checkedClass {
background-color:#3ab44a;
color:white;
}
</style>
</head>
<body ng-controller="TeamListCtrl">
<b>Teams</b>
<div id="teamCheckboxList" class="checkboxList">
<div class="uncheckedClass" ng-repeat="team in teams" ng-class="{'checkedClass': team.isChecked, 'uncheckedClass': !team.isChecked}">
<label>
<input type="checkbox" ng-model="team.isChecked" />
<span>{{team.name}}</span>
</label>
</div>
</div>
</body>
</html>
As of AngularJS v1.2.0rc, ng-class and even ng-attr-class fail with SVG elements (They did work earlier, even with normal binding inside the class attribute)
Specifically, none of these work now:
ng-class="current==this_element?'active':' ' "
ng-attr-class="{{current==this_element?'active':' '}}"
class="class1 class2 .... {{current==this_element?'active':''}}"
As a workaround, I've to use
ng-attr-otherAttr="{{current==this_element?'active':''}}"
and then style using
[otherAttr='active'] {
... styles ...
}
One more (in the future) way to conditionally apply style is by conditionally creating scoped style
<style scoped type="text/css" ng-if="...">
</style>
But nowadays only FireFox supports scoped styles.
There is one more option that I recently discovered that some people may find useful because it allows you to change a CSS rule within a style element - thus avoiding the need for repeated use of an angular directive such as ng-style, ng-class, ng-show, ng-hide, ng-animate, and others.
This option makes use of a service with service variables which are set by a controller and watched by an attribute-directive I call "custom-style". This strategy could be used in many different ways, and I attempted to provide some general guidance with this fiddle.
var app = angular.module('myApp', ['ui.bootstrap']);
app.service('MainService', function(){
var vm = this;
});
app.controller('MainCtrl', function(MainService){
var vm = this;
vm.ms = MainService;
});
app.directive('customStyle', function(MainService){
return {
restrict : 'A',
link : function(scope, element, attr){
var style = angular.element('<style></style>');
element.append(style);
scope.$watch(function(){ return MainService.theme; },
function(){
var css = '';
angular.forEach(MainService.theme, function(selector, key){
angular.forEach(MainService.theme[key], function(val, k){
css += key + ' { '+k+' : '+val+'} ';
});
});
style.html(css);
}, true);
}
};
});
well i would suggest you to check condition in your controller with a function returning true or false .
<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>
and in your controller check the condition
$scope.getTodayForHighLight = function(today, date){
return (today == date);
}
One thing to watch is - if the CSS style has dashes - you must remove them. So if you want to set background-color, the correct way is:
ng-style="{backgroundColor:myColor}"
Here's how i conditionally applied gray text style on a disabled button
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
styleUrls: [ './app.component.css' ],
template: `
<button
(click)='buttonClick1()'
[disabled] = "btnDisabled"
[ngStyle]="{'color': (btnDisabled)? 'gray': 'black'}">
{{btnText}}
</button>`
})
export class AppComponent {
name = 'Angular';
btnText = 'Click me';
btnDisabled = false;
buttonClick1() {
this.btnDisabled = true;
this.btnText = 'you clicked me';
setTimeout(() => {
this.btnText = 'click me again';
this.btnDisabled = false
}, 5000);
}
}
Here's a working example:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html

Toggling color of Text Input with Button click - jQuery

$("#btn").button().click(function() {
$("#textinput").css('color',function(clr) {
if ($("#textinput").css('color') == '#000000')
return '#ff0000';
else
return '#000000';
});
});
for some reason I cant toggle between the colors in input text. the .css docs of jQuery states the following:
Different browsers may return CSS color values that are logically but not textually equal, e.g., #FFF, #ffffff, and rgb(255,255,255).
in general, how can i get the property value of UI object (css values are constant?) ?
thnx!
I would create a class .white and a class .black and use .addClass() and .removeClass(). A html element can have multiple classes set
$("#btn").button().click(function() {
if ($("#textinput").hasClass("white"))
{
$("#textinput").removeClass("white").addClass("black");
}
else {
$("#textinput").removeClass("black").addClass("white");
}
});
I think someone will post a more elegant solution to this, because I think this is too much code for a simple task like this.
update:
Use toggleClass instead: http://api.jquery.com/toggleClass/

CSS text-transform capitalize on all caps

Here is my HTML:
small caps &
ALL CAPS
Here is my CSS:
.link {text-transform: capitalize;}
The output is:
Small Caps & ALL CAPS
and I want the output to be:
Small Caps & All Caps
Any ideas?
You can almost do it with:
.link {
text-transform: lowercase;
}
.link:first-letter,
.link:first-line {
text-transform: uppercase;
}
It will give you the output:
Small Caps
All Caps
There is no way to do this with CSS, you could use PHP or Javascript for this.
PHP example:
$text = "ALL CAPS";
$text = ucwords(strtolower($text)); // All Caps
jQuery example (it's a plugin now!):
// Uppercase every first letter of a word
jQuery.fn.ucwords = function() {
return this.each(function(){
var val = $(this).text(), newVal = '';
val = val.split(' ');
for(var c=0; c < val.length; c++) {
newVal += val[c].substring(0,1).toUpperCase() + val[c].substring(1,val[c].length) + (c+1==val.length ? '' : ' ');
}
$(this).text(newVal);
});
}
$('a.link').ucwords();​
Convert with JavaScript using .toLowerCase() and capitalize would do the rest.
Interesting question!
capitalize transforms every first letter of a word to uppercase, but it does not transform the other letters to lowercase. Not even the :first-letter pseudo-class will cut it (because it applies to the first letter of each element, not each word), and I can't see a way of combining lowercase and capitalize to get the desired outcome.
So as far as I can see, this is indeed impossible to do with CSS.
#Harmen shows good-looking PHP and jQuery workarounds in his answer.
I'd like to sugest a pure CSS solution that is more useful than the first letter solution presented but is also very similar.
.link {
text-transform: lowercase;
display: inline-block;
}
.link::first-line {
text-transform: capitalize;
}
<div class="link">HELLO WORLD!</div>
<p class="link">HELLO WORLD!</p>
HELLO WORLD! ( now working! )
Although this is limited to the first line it may be useful for more use cases than the first letter solution since it applies capitalization to the whole line and not only the first word. (all words in the first line)
In the OP's specific case this could have solved it.
Notes: As mentioned in the first letter solution comments, the order of the CSS rules is important! Also note that I changed the <a> tag for a <div> tag because for some reason the pseudo-element ::first-line doesn't work with <a> tags natively but either <div> or <p> are fine.
EDIT: the <a> element will work if display: inline-block; is added to the .link class. Thanks to Dave Land for spotting that!
New Note: if the text wraps it will loose the capitalization because it is now in fact on the second line (first line is still ok).
JavaScript:
var links = document.getElementsByClassName("link");
for (var i = 0; i < links.length; i++) {
links[i].innerHTML = links[i].innerHTML.toLowerCase();
}
CSS:
.link { text-transform: capitalize; }
What Khan "ended up doing" (which is cleaner and worked for me) is down in the comments of the post marked as the answer.
captialize only effects the first letter of the word. http://www.w3.org/TR/CSS21/text.html#propdef-text-transform
You can do it with css first-letter!
eg I wanted it for the Menu:
a {display:inline-block; text-transorm:uppercase;}
a::first-letter {font-size:50px;}
It only runs with block elements - therefore the inline-block!
May be useful for java and jstl.
Initialize variable with localized message.
After that it is possible to use it in jstl toLowerCase function.
Transform with CSS.
In JSP
1.
<fmt:message key="some.key" var="item"/>
2.
<div class="content">
${fn:toLowerCase(item)}
</div>
In CSS
3.
.content {
text-transform:capitalize;
}
If the data is coming from a database, as in my case, you can lower it before sending it to a select list/drop down list. Shame you can't do it in CSS.
After researching a lot I found jquery function/expression to change text in first letter in uppercase only, I modify that code accordingly to make it workable for input field. When you will write something in input field and then move to another filed or element, the text of that field will change with 1st-letter capitalization only. No matter user type text in complete lower or upper case capitalization:
Follow this code:
Step-1: Call jquery library in html head:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
Step-2: Write code to change text of input fields:
<script>
$(document).ready(function(){
$("#edit-submitted-first-name,#edit-submitted-last-name,#edit-submitted-company-name, #edit-submitted-city").focusout(function(){
var str=$(this).val();
str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
});
$(this).val(str);
});});
</script>
Step-3: Create HTML input fields with same id's you use in jquery code like:
<input type="text" id="edit-submitted-first-name" name="field name">
The id of this input field is: edit-submitted-first-name (It using in jquery code in step-2)
**Result:
Make sure the text will change after you move your focus from that input field at another element. Because we using focus out event of jquery here.
Result should like this: User Type: "thank you" it will change with "Thank You".
**
Best of luck
The PHP solution, in backend:
$string = 'UPPERCASE';
$lowercase = strtolower($string);
echo ucwords($lowercase);
I know this is a late response but if you want to compare the performance of various solutions I have a jsPerf that I created.
Regex solutions are the fastest for sure.
Here is the jsPerf: https://jsperf.com/capitalize-jwaz
There are 2 regex solutions.
The first one uses/\b[a-z]/g. Word boundary will capital words such as non-disclosure to Non-Disclosure.
If you only want to capitalize letters that are preceded by a space then use the second regex
/(^[a-z]|\s[a-z])/g
if you are using jQuery; this is one a way to do it:
$('.link').each(function() {
$(this).css('text-transform','capitalize').text($(this).text().toLowerCase());
});
Here is an easier to read version doing the same thing:
//Iterate all the elements in jQuery object
$('.link').each(function() {
//get text from element and make it lower-case
var string = $(this).text().toLowerCase();
//set element text to the new string that is lower-case
$(this).text(string);
//set the css to capitalize
$(this).css('text-transform','capitalize');
});
Demo
all wrong it does exist --> font-variant: small-caps;
text-transform:capitalize; just the first letter cap

How can I capitalize the first letter of an input?

I'm currently trying to capitalize the very first letter from an input.
Here's what I tryed :
fieldset input
{
text-transform:capitalize;
}
But it doesn't work the way I want, as every word is capitalized.
I also tryed this :
fieldset input:first-letter
{
text-transform:uppercase;
}
But it seems <input /> doesn't work at all with first-letter...
Anyway, do you have any idea of how to achieve this without javascript (or as little as possible) ?
JS: str.charAt(0).toUpperCase();
Impossible. It is possible with Javascript, or by putting only the first word within a span.
$('#INPUT_ID').keyup(function(){
if($(this).val().length>0 && $(this).val().length<5){
$(this).val($(this).val().charAt(0).toUpperCase()+$(this).val().substr(1));
}
});
Can't use length==1, as it doesn't work if user types fast.
Inputs can't have first letter capitalized only with CSS, not even :first-letter pseudoselector. We have to use Javascript.
We will use class name capitalized on every input for which we want to have the first letter capitalized.
HTML:
<input type="text" class="capitalized" />
The idea is to listen for change on input (focusout), take the value, capitalize first letter, join it with the rest of the value and set it as new value.
You can use keyup, but that becomes overkill after the first keyup - nothing will change there.
JS (jQuery flavor):
$('.capitalized').on('change', function () {
let entered = $(this).val();
let firstLetter = entered.charAt(0).toUpperCase();
let rest = entered.substring(1);
$(this).val(firstLetter + rest);
});
You must use
<fieldset>
<legend>DATA...</legend>
<input type="text" class="inputName" placeholder="Введите имя">
without <input />
then in CSS:
fieldset input {
text-transform: capitalize;
}

Resources