Welcome to the Question2Answer Q&A. There's also a demo if you just want to try it out.
+5 votes
1.6k views
in Q2A Core by
edited by

When developing plugins there is mostly the need to insert custom CSS. With q2a v1.6.3 we have two ways to add CSS to the pages:

1. inserting a CSS script in the head → problem is, each plugin causes an extra server request and the site gets slow (imagine 10+ plugins ...)

2. inserting CSS inline → problem is, the page gets bigger and loads slower

 

Idea for a better handling of custom CSS:

- let plugins specify custom CSS using a special qa_opt(), I would suggest something like qa_opt('CSS_PLUGIN', $value) where PLUGIN is the pluginid or the pluginname

- then the q2a core can cache* all qa_opt CSS entries into one qa_opt() field, e.g. qa_opt('CSSALL')

- and make one CSS "file" (head script) out of it, e.g. <link rel="stylesheet" href="http://www.q2apro.com/plugins.css" /> where plugins.css is picked up by q2a core / htaccess and throws back the css as text.


Main Advantages of  this approach:
- only one CSS script gets loaded, 1 request, independent from the number of plugins!
- all custom CSS in one place and not distributed over plugin.css files and inline CSS

What do you think?
Kai

 

cache* - not on every page load, but when the user goes to admin/plugin and changes things, and as soon as a new plugin is installed

Q2A version: 1.6.3
by
My opinion.
To store CSS, qa_options::content is too small (8KB). If we want to reduce requests, there may be a method to mix plugin CSS into theme CSS. However, plugin CSS may not always have to send like theme (e.g. profile page only). Therefore, I think CSS process should be possible to be able to choose either plugin side or core side.
by
@sama55: You are right, this could be the bottle neck. At least if we want to hold the css data of the "plugins.css" in a cache field. Maybe we should instead use PHP to really write this file into a folder?

3 Answers

+2 votes
by
edited by

This is apply to JS as well. During the MaxControl theme development I have stacked with some JS conflict and so many places now I'm loading scripts and CSS on request conditionally.

My opinion of having function plugin_exists() can reduce this too. Another option is to create two methods in core for CSS and JS same like wordpress . Which will have dependency measure in params.

Yesterday itself the same issue pops with my custom development for client for overriding methods. Two plugin conflicts. For now only possible way is to merge both into one.

This issue I consider as high priority. Now every time I make any plugin, have be ready to dig into all ugins to find conflicting one.

I hope we will get some solid solution for overriding methods and layer, script and CSS stacking.

I have published one blog on Q2A Market blog for the same to reduce plausibility of conflicting CSS and is.


Edit:

Just corrected typo due to mobile keyboard.... from is to JS

by
Thanks Jatin for agreeing. Exactly, the custom javascript is also affected. Here I would wish to have also only one file to be loaded.
+1 vote
by

How about a custom plugin that incorporates https://code.google.com/p/minify/ into Q2A? I gues this way Plugin / theme developers can simply add CSS / JS files to the header / footer and minify will take care of joining them together. For my Simple Social Sharing plugin I am outputting CSS in the header rather than adding another css file beacuse same reason - minimise extra http request.

by
Wow, interesting tool. Thanks for the hint. Let's see what the core developers think about it! Kai
+1 vote
by
edited by

My thoughts on the proposal of the question is a no go. I would avoid storing CSS in the DB. One reason is already explained by sama55 in a comment and it should be enough.

Regarding Jatin's answer I think it has a several points to discuss, but just a few actually related to the question. I'll go through all of them:

1. Storing JS in the DB (if that is the idea too) is a no go either, IMO

2. Regarding JS/CSS conflics I believe they should be tackled by just following convetions (http://www.question2answer.org/qa/31654/). I don't really know what kind of issues you've faced but following those practices should simplify things.

3. If the conflicting issue is actually JS libraries import (eg, 2 plugins importing jQuery UI, bootstrap, etc) then the issue is much deeper than it seems. I've thought in many alternatives but none is great.  The best thing you can do is allow the user to disable ALL those libraries at will. That way, if a plugin previoiusly imported a library then the user can disable the import from your plugin

4. It doesn't exist such a funcion (plugin_exists()) but you can play a bit with modules existance to reflect this behaviour. Take a look at the core.

5. You mentioned overriding methods. If you are talking about an override (http://www.question2answer.org/overrides.php) then you're in deep trouble. Plugins should try to avoid at all means these overrides and I wouldn't recommend publishing such a plugin unless it has a huge WARNING. That can brake many things. If you're talking about layer methods being overriden then again, then there are 2 options. One of them is poorly designed and it overwrites some qa_content key or HTML does not look good when the 2 plugins are active. In the first case, you'll have to fix the plugin yourself or complain to the plugin's author :) In the second case, I will have to tell you that the issue happens "by design". It is impossible to be sure how your plugin will fit in a different Q2A installation with plugins you've never seen. Sadly, the 100% best way to go, IMO, is not a technical answer, because right now, the core is not ready to handle this situation, but rather a disclaimer will get you out of trouble next time :D

Switching to dkd903's answer, I have to say it sounds pretty good but will only be useful for static CSS / JS files that should be included in every request. This considerably limits the benefits of doing so. Consider the following situations:

1. Let's take the simplest example of being able to disable a plugin that has a huge static CSS file. If you had a full minimized CSS file with all the CSS files of all plugins classes inside then you will still be returning the CSS classes for the disabled plugin. It would only be worth if the plugins had small CSS files. Some don't. Same applies to JavaScript libraries not used on every request.

2. JS usually has a dinamic component. I'm talking about your custom JS code rather than static libraries in this case. It is most likely that you have to perform a PHP echo to send data from PHP to JS. And you cantt minimize that in a static JS file. Even if you remove the echo and perform an AJAX request in order to keep the JS static you'd still be performing an additional HTTP request which was exactly what you wanted to avoid in the first place.

3. There is an additional situation to handle which is user related. How and when will you be compressing the files? On each PHP request is, clearly, a no go. Best approach woud be to let the user manually fire the event and, probably, after each plugin saves their data. The latter one is easy to understand why. The former one is justified because a user might change a CSS plugin file directly from the static file that is supposed to be compressed and then expect a change in the application. Then the user will know that they have to click a "Minify" button to do so. Also, plugins will have to register their static CSS and JS file with the core in order for this to be possible. Of course, this would require core changes. And don't forget about plugin uninstallation...

My conclusion: These proposals result in little benefit for too much effort for core developers, plugin developers and even the user. I do agree, however, that there must be a way to improve static CSS/JS imports. I just can't figure it out now :(

by
Thanks for your thoughts. The idea for putting small chunks of CSS into qa_opt-fields just came to me when I faced the issue. I am glad that we discuss this now to hopefully find the best solution.

After dkd903's answer I thought one way to go would be having a styles.css and a script.js for each plugin, and combining all of them with the minify tool. The "dynamic" component you mention, mhh, I have not seen so many spots in plugins where the JS code created relied on PHP. I'm not talking about the core (which is still not using sufficient jquery in my point of view). Many plugins use jquery that is so mighty to get your way around, I guess.

For the changed CSS: If the user changes CSS it should happen in the theme's css file.

Let's see if Scott or gidgreen will find the time to read our ideas and conclude ;)

Regards, Kai
...