So a little disclaimer: I am completely and utterly self taught. Bear over with me if I'm being a clown.
Anyways, I am currently working on a some platform and in need for a dropdown functionality. That's simple right? Just use HTML5 select tag. However option tags can't be styled :>
So onwards to build my own. The HTML5 select tag uses keyboard input (up/down/enter) for those with disabilities, and I thought I would implement that too. That did present a problem though: The :hover selector collided with my custom attribute, which I use to style keyboard selected items (&[data-selected=true] to be precise).
So onwards to implement my own :hover. And this is where my bewilderment starts.
const handleChildMouseOver = () => {
const items = Array.from(listItem.current?.children!); // The wonders of typescript XD
for (const item of items) {
if (item === event.target) {
item.setAttribute("data-selected", "true");
} else {
item.removeAttribute("data-selected"); // I'm removing the attribute, rather than toggling it, because I got components with 3 states: On, off, and default.
}
}
}
(...)
<ul css={css.list} /*emotion prop*/ data-toggled={toggled} /*parent state*/ onMouseOver={handleChildMouseOver}>
{children} // parent prop
</ul>
So it works as intended, which is fine. But I recall from my pre-react days that you should never manipulate the DOM in loops, as it causes repaints on every iteration. However when I look at the Dev Tools performance profiler, I barely see any "Paints", 8 or so, even when I'm switching hover targets like a madman. What I do see is one million "Composite layer". Oh, and as a bonus React doesn't re-render. Which is fine right? 'Cause I'm not really changing the state of anything, just adding some CSS.
So my question boils down to: Am I being bonkers or smart?
N.B.: I would love to share the actual component, but seeing as this is my first post on stackoverflow, I've got no clue how you do those fancy script tag. Well github is involved somehow, I know that much 🤔
Related
I'm migrating my site from Bootstrap to Tailwind 3 and, in the process, built-in solutions (Dropdown, Tabs, Accordion...) needed to be replaced with alternatives. The section I'm working on right now is a custom Comments Editor I created.
I'll leave a link to what Tailwind's Playground generated for me in a CodePen because the code is longer than the maximum number of allowed characters here. The decision to create a Pen is only because in the Playground it doesn't work as the anchors open in new windows/tabs.
Anyway, the code that really matters, what makes the tabs work, is this one:
[data-target] {
scroll-margin-top: 10rem;
}
[data-target]:last-of-type + [role="tabpanel"], :target + [role="tabpanel"]{
display: flex;
}
[role="tabpanel"], :target ~ [data-target]:last-of-type + [role="tabpanel"]{
display: none;
}
As the title says, I'm looking for a way to change the background-color of the tabs, hinting to the User which one is currently active.
To accomplish that, I would need to switch Tailwind's bg-color-0 with bg-color-100 and take border-b-color-0 out of the once active tab and give it to the new one. But I don't know if I can do that only with CSS.
Not add/remove the classes per se, only their corresponding styles
I've seen a lot of implementations of Pure CSS Tabs, and all of them used hidden <input> fields. Though this implementation doesn't use them, I've added and named them accordingly, but I could only target them with CSS if the User clicked exactly where they're positioned (top-left of the tabs) instead of any part of them.
I'm aware I'll eventually have to add JS to switch the ARIA attributes, but is the basic functionality possible to be accomplished with CSS only? If not, is there an alternative implementation with which I could?
Thank you for your time :)
Let's say for example I'm going through my stylesheet but I can't remember what element a certain CSS selector affects.
Is there any method, tool, or anything that I could do/use to find out what exactly it is affecting?
Thanks!
I just opened up a random bootstrap template site and did what you where asking for.
Open up your chrome browser (I prefer this as I feel this is easy to debug both Jquery and css) and Press F12, you will get a developer window as in the image.
Switch to the console tab.
Use Jquery selector to select all
the intended elements (you can use the same css selector here too
but just place them inside $('')) Eg: $('.tab-content') I am trying to find out all the elements with the class tab-content
The result is all the elements
of that selector.
NOTE: This appraoch woud require you to have Jquery loaded into your page. Else the script will throw an error saying $ is not defind.
In addition to using your browser's development tools, there are two easy ways to do it that should work in almost any browser (no matter how bad the developer environment).
Visually
Temporarily set a border or background color for the selector, like:
border: 1px solid red;
Or:
background: red;
This makes it very easy to find the affected elements.
Programmatically
On the JavaScript console, use:
// Replace with something that prints the relevant details
var stringify = function(element) { return element.innerHTML; };
// Iterate over all affected elements and print relevant info
var affectedElements = document.querySelectorAll('.your .selector');
var len = affectedElements.length;
console.log('Elements affected: ' + len);
for (var i = 0; i < len; i++) {
var affectedElement = affectedElements[i];
console.log(
'Element ' + (i+1) + ':\n' +
stringify(affectedElement) + '\n\n');
}
The inspection of elements feature of the browser is meant for the purpose you want.
1.Open up the index file in any browser(preferably Mozilla Developer edition),
2.Right click and Inspect element,
3.Then open the compiled stylesheet. Find out the style element you want to check the effect of.
4. Go back to inspection, remove/add CSS properties and see the effect in real time.
The other way is to use Adobe brackets. It's live preview feature will highlight the section that involves the code snippet, you point your cursor to.
This one is bit tricky ,
I created jsfiddle here
http://jsfiddle.net/WXmcL/10/
to kinda replicate the https://chrome.google.com/webstore/category/home
addons containers. all is fine except that a element link.
I need to position the
<a class="link" href="linktoapp"></a>
correctly but also let the users reach the
Info1
since I cant have any ul or divs inside the a element I am not able to achieve this effect. Yes I can do spans but my ratings contain ul , divs etc and I would have more markup inside it. If you check on chrome store you can always link to the app and in same time reach the rating. They put all the elements inside the a tag but the page validation is not seeing it. So it seems to me that is being done with js on load or ?
Thank you!
you should forget about validation whilst you are building your effects for a while. get it to work with the markup you need, then you can sit back and take away what won't validate and inject it via javascript.
mootools has a wonderful Element constructor.
new Element("a.linktoinfo[html=Info]").inject(element);
you can pass on any property into it via the constructor options object.
eg.
new Element("a", {
"class": "foo",
"href": "#",
"events" : {
click: function() {
showInfo(this.getParent());
}
}
}).inject(element.getElement("a.link", 'after');
etc etc.
btw when you morph classes, just make sure it morphs the properties you differ. in your case, it makes sense to make .myInfoOn / .myInfoOff that have the different heights. there is no point in assigning a morph between other values that have not been changed.
that type of morph parses all the css rules defined in the class that you pass on every event and in reality, you are better off setting it manually. it will scale less if it's hardwired, I realise that - but you can set as a variable into your class.
Is it possible to create a new property in CSS? For example, say you're developing a control that displays a photo and you want to add a property to css to control what style frame to have around the photo. Something like:
#myphoto { frame-style: fancy }
Is there some way to do this in a cross browser compatible manner, and how would you define whether the style inherits or not?
EDIT: It's a custom control - your JS code would deal with the style - I'm not expecting the browser to magically know what to do. I want the user to be able to style the control with CSS instead of JS.
Sure, why not. Check this out as an example: http://bililite.com/blog/2009/01/16/jquery-css-parser/
You may also be able to get away with using CSS classes instead of properties. Not sure if that works for what you're doing.
You can't. Browsers interpret CSS based on how their layout engines are coded to do so.
Unless you took an existing open source engine like WebKit or Gecko, added custom code to handle your custom CSS and made a browser that used your customized layout engine. But then only your implementation would understand your custom CSS.
Re your edit: it'd depend on whether you're able to read that style somehow. Typically browsers just instantly discard any properties they don't recognize, and CSS is not normally reachable by JavaScript because CSS code is not part of the DOM.
Or you could look at Jordan's answer.
If you'd prefer a straight JavaScript solution that uses no JS libraries, you could use the query string of a background-image to keep "custom properties" inside your CSS.
HTML
<div id="foo">hello</div>
CSS
#foo {
background: url('images/spacer.gif?bar=411');
}
JavaScript
getCustomCSSProperty('foo', 'bar');
Supporting JavaScript Functions
function getCustomCSSProperty(elId, propName)
{
var obj = document.getElementById(elId);
var bi = obj.currentStyle ? obj.currentStyle.backgroundImage : document.defaultView.getComputedStyle(obj, null).getPropertyValue('background-image');
var biurl = RegExp('url\\(["\\\']?([^"\\\']+)["\\\']?\\)').exec(bi);
return getParameterByName(propName, biurl[1]);
}
function getParameterByName(name, qs) {
var match = RegExp('[?&]' + name + '=([^&]*)').exec(qs);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
Demo:
http://jsfiddle.net/t2DYk/1/
Explanation:
http://refactorer.blogspot.com/2011/08/faking-custom-css-properties.html
I've tested the solution in IE 5.5-9, Chrome, Firefox, Opera, and Safari.
I have a data entry web app where the control that has focus is given a yellow background color (and when the user navigates away, it turns back to white). The script to do this came from I-don't-know-where, and it breaks in IE7 causing all sorts of problems, like drop downs not working (the script was designed to work on textboxes and drop downs, or at least it was implemented with that in mind), and it works in ie6.
Some of my users have been switched to Ie7 without my being informed, and the rest will go to ie7 at some future time. So, I'd like to implement a friendlier solution. I really like jquery and am already using it on the app for a variety of things. Also, it has been suggested that cross browser support may/will eventually be important on the intranet.
What I would prefer to avoid is manually adding a bunch of onblur="SomeMethod()" (or something similar) to the controls (There must be 600+ in the app). In fact, if I tell my boss this he's probably going to throw something at me.
I am already using JQuery in the application. Where it is used function calls are explicit, and are all called in onblur.
Currently, I am of the mind to do something like this:
$(document).ready (function(
$(':text').focus(function()
{
//Do Highlighting
}
$(':text').blur(function()
{
//Good bye highlighting
}
)
Am I on he right track? Is onblur my best option? Is there a better way?
the other onblur functions show/hide child fields based on the value of the parent. I realize I am not providing code, but am I setting myself up for any conflicts?
Use jQuery's blur() and focus() methods.
Also, I think you mean to REMOVE highlighting with your blur function (blur means the user has clicked off of the element in question). Use focus() to turn on the highlighting.
$(document).ready (function() {
$(':text').focus(function() {
$(this).addClass('highlight');
});
$(':text').blur(function() {
$(this).removeClass('highlight');
});
});
There seems to be a workaround that makes the :focus pseudo-class work in IE6/7. I haven't used it myself but I think it's quite a established solution:
http://www.xs4all.nl/~peterned/csshover.html
With 600+ elements, a scriptless workaround is probably preferable, especially if older clients are involved.
$('textarea, input:text').focus(function() {
$(this).addClass('hilite');
}).blur(function() {
$(this).removeClass('hilite')
});
.hilite {
border: 2px solid gray;
}
blur/focus will work for you. If you're able, at some point, to move all your users all the way to IE8 you can also accomplish the desired effect with CSS:
input[type=text]:focus {
background-color: lightyellow;
}
This doesn't answer your question, but is an alternative... jQuery Tools Expose will apply an overlay to all elements outside your input box thus forcing the user to focus on the input. It's a nice feature and the plugin is very lightweight. I also posted some coding that does the same thing in this answer in case you don't want to use a plugin.
There is a free widget library for this task: Focus highlight widget.