Per-User CSS

By Ed JohnsonEd Johnson

Description

The basic purpose for this technique is so we can apply CSS rules that override some default CSS settings on a per-user basis. For the purposes of this article, we'll create a couple of CSS classes that will hide data for all users by default. We'll create 2 classes — one for hiding block elements and one for hiding inline elements. Then, we add the CSS for our default state to the nav:side page (would also work with nav:top)). We'll also add a ListUsers module that will render the CSS to override the default for individual users that we specify.

Background

There is a great snippet written by James Kanjo called Specific Users Only Include. I have used that snippet many times since he created it in April of 2010. There are 2 issues with the SUO Include. The first is due to restrictions and limitations of Wikidot: The use of Modules inside the SUO code is prohibited. The second is a minor complaint: If you have a lot of pages that use the SUO code, it can be hard to maintain. This is especially true if you have to frequently edit the list of specific users.

Another idea by James (Per-category CSS), where he made use of the fact that our sites navigation pages are almost always "present" (but not necessarily visible), got me thinking about a different way to control the display of data to specific users. What I like about this technique is that you can use it inside modules and maintenance is much easier.

A note about security

This technique does not securely hide data from those who know where to look. Anyone viewing the HTML source of your pages will be able to see the content that is hidden using this technique.

Set up nav:side to hide data by default

Add this code to your nav:side or nav:top page:

[[module CSS]]
.show-data, .show-data-inline {
    display: none;
}
[[/module]]
[[div style="display: none;"]]
[[module ListUsers users="."]]
[!-- remove the leading space on the line below on your live page --]
 [[include css:%%name%%]]
[[/module]]
[[/div]]

Create the override CSS "master" page

Create a page called css:admin-css with this code:

[[module CSS]]
/* use this class for block elements like divs */
.show-data {
    display: block !important;
}
/* use this class for inline elements like spans */
.show-data-inline {
    display: inline !important;
}
[[/module]]

Create individual user pages

For each user that you want to apply the per-user CSS code to, create a page called css:user-name where user-name is the Wikidot unix name of the user. For example:
css:ed-johnson for Ed JohnsonEd Johnson
css:robelliott for RobElliottRobElliott
css:james-kanjo for James KanjoJames Kanjo
On each user's page, add this code:

[!-- remove the leading space on the line below on your live page --]
 [[include css:admin-css]]

How it works

This technique takes advantage of the ListUsers module by replacing %%name%% above with the Wikidot unix name of the user who is currently logged in.

If the page name created inside the ListUsers module code matches the per-user page name you created, the page to be included exists and the CSS on that user's page will become active, overriding the default CSS. If there is no match, the page to be included does not exist and the default CSS for our two classes is not overridden. We wrap the ListUsers module in a display: none div block so that the normal error message generated by the include syntax when a page doesn't exist is not visible. But, visible or not, the code in a CSS module will always be active.

Example for block elements

You'd like to have an admin menu that is visible to only authorized users of your site. You can add something like this to the bottom of your side navigation page (nav:side):

[[div class="show-data"]]
Admin Options
[/nav:top/edit/true Edit Top Navigation]
[/nav:side/edit/true Edit Side Panel]
[/css:theme View CSS] - [/css:theme/edit/true Edit CSS]
[/admin:manage Site Administration]
[[/div]]

Example for inline elements

You'd like to display a list of recipes you've collected on your site with links to the pages for all users. You'd also like to display an option where admins or other authorized users can go directly to edit the recipe pages.

+++ Recipe List
[[module ListPages category="recipe"  order="name" separate="false"]]
%%title_linked%% [[span class="show-data-inline"]]([/%%fullname%%/edit/true edit this recipe])[[/span]]
[[/module]]

Maintaining users

The thing I like about this technique is that it's very easy to add and remove users who are "authorized" to view certain content on my sites. To add a user, I just create a new css:user-name page. To remove a user, I simply delete the css:user-name page.

Other possibilities

It would be possible to create multiple levels of visibility by creating multiple pages to be included. For example. you might expand on this idea by creating these pages:
css:admin-css
css:editor-css
css:author-css
css-manager-css
css-hourly-employee-css
css-corporate-staff-css
etc.

Then you would just have to add a new set of CSS classes for each group:

[[module CSS]]
.show-admin, .show-admin-inline {
    display: none;
}
.show-editor, .show-editor-inline {
    display: none;
}
/* etc */
[[/module]]

Then on the css:user-name page, just include the appropriate css page for that user. Using the recipe list example from above, you might change it to look like this to allow editors and admins to see the edit link:
+++ Recipe List
[[module ListPages category="companyforms"  order="name" separate="false"]]
%%title_linked%% [[span class="show-editor-inline show-admin-inline"]]([/%%fullname%% edit this page])[[/span]]
[[/module]]

The admin user's page would look like this:
[!-- remove the leading space on the line below on your live page --]
 [[include css:admin-css]]

The editor user's page would look like this:
[!-- remove the leading space on the line below on your live page --]
 [[include css:editor-css]]

I'm sure you can come up with other uses as you explore this technique.

Have fun!

In Action

I have set up a small demo on the community playground:
Per-User CSS Demo Page


Thanks to tsangk for this great snippet: conditional-blocks


text above inserted with:

[[include :snippets:if START |unique=1|type=equal|var1=%%name%%|var2=conditional-blocks]]
**##red|Thanks to tsangk for this great snippet:##** [[[code:conditional-blocks]]]
[[include :snippets:if END]]



Other snippets posted by Ed Johnson


Rate this solution

If you think this solution is useful — rate it up!

rating: +6+x
Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License