How to use ng-class with CSS transitions? - javascript

I have an element set to display: none; height: 0px and I want to add classes to it that makes display: block; height: 200px; with a CSS transition on the height. The problem is the transition - for it to work, the element has to be display: block first before changing the height.
So $el.addClass("display-block full-height") doesn't show the transition, as it adds both classes at the same time.
This jQuery does work though:
$el.addClass("display-block");
$el.width(); // <-- Forces a browser redraw of the element before proceeding
$el.addClass("full-height");
What I'd like to know is how I get this working with AngularJS's ng-class ? It seems like the only way is to add both classes at the same time, which doesn't work as above. Is there a good solution, either a way that forces a redraw in the same way or something else?
I could do a custom directive if that's the only answer, but I'd prefer a better way if possible.

What you need is "Class and ngClass animation hooks" from https://docs.angularjs.org/guide/animations
I edited the given plunker to meet your need (you still need to implement the height though)
BUT animation with display:none and display:block is working here
http://plnkr.co/edit/oH0hh8I1BAPuPz81AqHZ?p=preview

Related

Adding a Class vs Removing a Class to Show Elements on a Web Page

Current Design
In a website I am designing I have a number of elements that initially will appear hidden, until the user needs to see them. For example they have scrolled to a desired height on the page.
Currently this works by JavaScript adding a class line.classList.add('show-header-line');
Which in CSS will be defined next to the main styling for the element. This show variant of the class will only contain attributes required to make the element visible opacity: 1. The main styling for the element will contain the opposite attributes required to hide the element initially opacity: 0.
The Alternative
Of course this could work the other way around. With a class designed to hide the element initially being set in the html, then to be removed when required by JavaScript.
HTML
<div class="header-line hide-header-line" />
JS
line.classList.remove('hide-header-line');
Note
Of course I could add and remove styles directly (without the need for extra classes) in the JavaScript, but this seems much worse. Regarding a lack of separation of concerns.
Question
My current approach means the resulting rendered DOM is littered with elements that have main style class and a show class. The alternative means my html file is littered with elements with a main style class and a hide class. Which is considered better practice? Is there another cleaner way I could be doing this?
I would strongly suggest against using opacity:0 for this, rather use display: none. The reason being that an element with opacity: 0 still occupies space in the markup, whereas display: none will add the element to the DOM, but it won't be rendered in the markup (if that makes sense).
Here is a more detailed explanation
Also, an example using the scroll pass certain point you said, this is how I would do it, note code is untested.
window.addEventListener('scroll', function(){
document.querySelector('#navigation').classList[this.scrollTop > 200 ? 'add' : 'remove']('fixed-nav');
});
css
.fixed-nav {
width: 100%;
position: fixed;
top: 0;
left: 0;
}

How to make a hidden (ng-cloaked) item preserve the space it takes up when its visible

In a table... I have action buttons that appear when the mouse goes over that row by using ng-cloak and ng-show.
The problem is, when the icon appears, it takes up more space than when its not there, and the html around it jumps.
I even set my css to use display:none for ng-click, which I thought is supposed to preserve the space the hidden element takes up (as opposed to visibility: hidden).
How can I fix this? OR can you think of a better way to do this?
<tr id="treeHistoryItem" ng-repeat="o in tree.history"
ng-mouseover="showEdit=true" ng-mouseleave="showEdit=false">
....
<td align='right'>
<a ng:cloak ng-show="showEdit" href
ng-click="removeTreeRec(o.$$hashKey)"
class='fa fa-times _red _size6' ></a>
</td>
</tr>
Here's a plunkr example:
http://plnkr.co/edit/POA9b2pZA9QbBgcMsxBE?p=preview
ngCloak is used to
prevent the Angular html template from being briefly displayed by the
browser in its raw (uncompiled) form while your application is
loading
The correct place to put it would be way further up in the DOM tree but it's really meant to solve a different problem than this. I would try just going with ngShow here and rather override its CSS class, .ng-hide to do visibility: hidden; rather than display: none;
(Visibility is the one that preserves space, not display).
As noted in the docs for ngShow you will need to use !important to override the display: none; property.
Note, in the version of Angular you were using in your plunker, ngShow is adding an inline style to the hidden element. I am not sure which version moved away from that but I could not get this approach to work with 1.0.5.
Here's it working with your plunker, but with the most recent Angular version:
Plunk
Late to the party, however...
In my case, whenever I need to do this i use ng-class. If you copy the code from your ng-show and put it into:
HTML:
ng-class="{'disabled': showEdit}"
ng-click="showEdit && removeTreeRec(o.$$hashKey)"
CSS:
.disabled {
visibility: hidden;
cursor: default;
}
Cursor:default simply makes the cursor not change for usability purposes.
Hope this helps!
EDIT: in this case adding the cursor and showEdit to the ng-click probably wont make a difference as the icon will always be shown if the mouse is over the icon due to the hover event, but nonetheless I think it's good practice to cover all bases
You can do that using css. You can put to your <tr> a height.
you can assign height to your containers which sometimes isn't practical because you don't always know the content height up front. or you could change your classes content declaring them to be
.not_remove.ng-cloak,.not_remove.ng-hide{
display:block;
visibility:hidden;
}
note the .not_remove class. this will enforce this new behavior only on elements who have the no_remove class. the display property can be setted to what ever flow your element follows

Referencing another element in CSS / doing math in CSS

I have two divs nested inside of a div.
<div id='outter' class='one'>
<div id='inner'></div>
<div id='button' class='bttn'>Click me!</div>
</div>
The outter div's height is a percentage of the page. I'd like one of the inside div's height to be a fixed difference away the outter div (i.e. $('#inner').height($('#outter').height() - 35)), because the second inner div is essentially a button with fixed height (35). I'd like this to happen even when I change the height (through CSS triggers (:hover/adding a class/etc. so I can use Transitions) or otherwise).
I googled around a bit and saw Less might be an answer, but from what I can tell it compiles in to static values, but I still need to use percentages, since I want this app to work/feel the same on any screen size.
I have examples of what I'm currently doing/how I'm thinking about it in some jsfiddles.
Current 'solution': http://jsfiddle.net/L9NVj/5/ (End heights are what I want them to be, but the transition looks terrible)
Idealistic 'solution': http://jsfiddle.net/L9NVj/6/ (End heights are wrong, but the inner div hugs appropriately)
Potential solution: http://jsfiddle.net/L9NVj/7/ (This hides the inner div on click and then shows it again when the appropriate size has been reached)
Any help/thoughts/insights would be greatly appreciated!
Consider absolute-positioning the inner elements, since the outer's size isn't controlled by their size/position.
#inner {
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 35px;
/* ... */
}
.bttn {
position: absolute;
bottom: 2px;
left: 2px;
/* ... */
}
Example: http://jsfiddle.net/L9NVj/9/
How about conflicting absolute positioning. To do it, you'd just need to set the top, bottom, left and right of the #inner element and then transition those. That will maintain the distances around the edges of the element, and allow other positioning as well.
Note that while you don't need to actually calculate the value in this case, in the future, calc() can be used to calculate a dynamic value in CSS. In that case, you could do something like height: calc(100% - 37px); to get the same effect.
CSS3's calc() is the answer you're looking for, in combination with a JavaScript fallback for browsers that don't support calc(). In your 'Idealistic solution' fiddle, change your CSS height definition to the following:
height: -webkit-calc(100% - 35px);
height: calc(100% - 35px);
While normally you should include all prefixes (and you still may need to, depending upon your level of browser support), according to Can I Use, the only browsers that currently need prefixing are -webkit browsers.
What I would do with this knowledge is the following: grab a feature detection script, I really like Modernizr and detect to see if calc() is available in the browser. Modernizr has a non-core detect for calc() that you can use. Use that CSS in your CSS file as the default, then using a resource loader such as yepnope (comes with Modernizr), load in a JS solution if calc() isn't available.
Of your JavaScript solutions, I'd probably suggest your "Potential Solution" option, but instead of jQuery's hide() and show(), set opacity to 0 and 1 and use a CSS3 transition to transition between the two. I'd also not rely upon a timeout, but rather use the transitionend JavaScript event.
I edited your first jsfiddle little bit i think that's what you wanted. Just added line.
$(window).resize(function(){$('#inner').height($('#outter').height() - 35)});
jsfiddle:http://jsfiddle.net/Qqb3g/
You may have to some workaround to make transition smooth when button the button is clicked.
you need to calculate the inner div in %, so it can resize belong outer div, change your js code to this :
//calculating inner div'x height in % of outer
$('#inner').height((100 - (33/$('#outter').height() * 100)) + '%');
$('#button').click(function () {
$('#outter').toggleClass('two');
});
give a try to DEMO

CSS for dynamic inserted elements

Currently I'm working on a website where I'd like to show some toolstips for specific DIV elements. My weapon of choice is jQuery Tools.
So when I use $(".toolTipMe").tooltip(); it works quite nice. As soon as I hover the element a new DIV appears in the DOM:
<div class="tooltip" style="display: none; position: absolute; top: 313.65px; left: 798.5px;">foo</div>
However the design is done by our very own css-monster (you should this this guy!) and he's using a a lot of z-indexes so the .tooltip-DIV is behind the other elements.
Now the question:
The following code in our .css File is not having any effect:
.tooltip{
z-index: 9001;
}
In fact the attribute is not even showing up when debugging the website. But the following will work:
$(".toolTipMe").tooltip({
onShow: function(){
$(this).css("z-index","9001");
}
});
I'm not sure how CSS Rules are applied for dynamic inserted DOM Elements but what I really detest in the current workaround is the mixture of functionality and style. Any chance to clean up this mess? :C
I am not familiar with jquery tools, but if your z-index is not working you must need a !important tag or making it position:relative or position:absolute
In jquery tools tooltip you need to specify the z-index inside the tooltip constructor like:
$(".toolTipMe").tooltip({ z-index: '9001'});
I'm not sure if it is z-index or zindex.. check it out

remove / reset inherited css from an element [duplicate]

This question already has answers here:
How to reset/remove CSS styles for a specific element or selector only
(17 answers)
Closed last month.
I know this question was asked before, but before marking it as a duplicate, I want to tell you that my situation is a little different from what I found on the internet.
I'm building and embedded script that people can put it on their sites. This script creates a div with a certain width/height and some information in it.
My problem is that some websites declare styles for div that are inherited by my div as well.
for example:
div{
background-color:red;
}
so if I don't set any background color to my div, it will show red even if I don't want that.
The only solutions I come along is to overwrite as many css proprieties, this way my div will show exactly as I want.
The problem with this solution is that there are too many css proprieties to overwrite and I want my script to be as light as it can be.
So my question is if you know another solution to my problem.
It can be in css/javascript /jQuery.
Thanks
"Resetting" styles for a specific element isn't possible, you'll have to overwrite all styles you don't want/need. If you do this with CSS directly or using JQuery to apply the styles (depends on what's easier for you, but I wouldn't recommend using JavaScript/JQuery for this, as it's completely unnecessary).
If your div is some kind of "widget" that can be included into other sites, you could try to wrap it into an iframe. This will "reset" the styles, because its content is another document, but maybe this affects how your widget works (or maybe breaks it completely) so this might not be possible in your case.
Only set the relevant / important CSS properties.
Example (only change the attributes which may cause your div to look completely different):
background: #FFF;
border: none;
color: #000;
display: block;
font: initial;
height: auto;
letter-spacing: normal;
line-height: normal;
margin: 0;
padding: 0;
text-transform: none;
visibility: visible;
width: auto;
word-spacing: normal;
z-index: auto;
Choose a very specific selector, such as div#donttouchme, <div id="donttouchme"></div>. Additionally, you can add `!important before every semicolon in the declaration. Your customers are deliberately trying to mess up your lay-out when this option fails.
You could try overwriting the CSS and use auto
I don't think this will work with color specifically, but I ran into an issue where i had a parent property such as
.parent {
left: 0px;
}
and then I was able to just define my child with something like
.child {
left: auto;
}
and it effectively "reset" the property.
Technically what you are looking for is the unset value in combination with the shorthand property all:
The unset CSS keyword resets a property to its inherited value if it inherits from its parent, and to its initial value if not. In other words, it behaves like the inherit keyword in the first case, and like the initial keyword in the second case. It can be applied to any CSS property, including the CSS shorthand all.
.customClass {
/* specific attribute */
color: unset;
}
.otherClass{
/* unset all attributes */
all: unset;
/* then set own attributes */
color: red;
}
You can use the initial value as well, this will default to the initial browser value.
.otherClass{
/* unset all attributes */
all: initial;
/* then set own attributes */
color: red;
}
As an alternative:
If possible it is probably good practice to encapsulate the class or id in a kind of namespace:
.namespace .customClass{
color: red;
}
<div class="namespace">
<div class="customClass"></div>
</div>
because of the specificity of the selector this will only influence your own classes
It is easier to accomplish this in "preprocessor scripting languages" like SASS with nesting capabilities:
.namespace{
.customClass{
color: red
}
}
Try this: Create a plain div without any style or content outside of the red div. Now you can use a loop over all styles of the plain div and assign then to your inner div to reset all styles.
Of course this doesn't work if someone assigns styles to all divs (i.e. without using a class. CSS would be div { ... }).
The usual solution for problems like this is to give your div a distinct class. That way, web designers of the sites can adjust the styling of your div to fit into the rest of the design.
As long as they are attributes like classes and ids you can remove them by javascript/jQuery class modifiers.
document.getElementById("MyElement").className = "";
There is no way to remove specific tag CSS other than overriding them (or using another element).
you may use this below option.
<style>
div:not(.no_common_style){
background-color:red;
}
</style>
now , if their any place where you do not want to apply default style you can use 'no_common_style' class as class.
ex:
<div class="no_common_style">
It will not display in red
</div>
From what I understand you want to use a div that inherits from no class but yours. As mentioned in the previous reply you cannot completely reset a div inheritance. However, what worked for me with that issue was to use another element - one that is not frequent and certainly not used in the current html page. A good example, is to use instead of then customize it to look just like your ideal would.
area { background-color : red; }
One simple approach would be to use the !important modifier in css, but this can be overridden in the same way from users.
Maybe a solution can be achieved with jquery by traversing the entire DOM to find your (re)defined classes and removing / forcing css styles.

Categories