How to Update CSS Property in external style sheet via Laravel? - php

I am working on a project where i am allowing the user to change theme settings i.e colors, design etc from Admin Panel. I want the user to just enter the color hex code and that will change the linked properties in the view. What i tried to do is
In the view:
<style>
button.submitform:hover, button.submitform:focus{
background: {{ $customizer->global_lite_colorcode}} !important;
}
</style>
This solution work perfect but it has to be inline or in the html file, but i want to use externel css file.And this style i.e button.submitform lives in external css file called main.css . I want the laravel variable to change that property in there. How can i do this ?

I don't think that your css file main.css can parse notation of Laravel {{}}. Of course, if you must style pseudo classes like hover or focus, I have an idea about this, I think you can set a fixed style firstly:
button.submitform__red:hover, button.submitform__red:focus{
background: red !important;
}
And dynamically bind style with {{}} like this:
<button>
<div class="submitform__{{$customizer->global_lite_colorcode}}" />
</button>
js way:
document.querySelectorAll('.submitform__{{$customizer->global_lite_colorcode}}')[0].style['background'] = '{{$customizer->global_lite_colorcode}}';

Since you are dealing with a User (who is probably logged-in), you can very easily create CSS Styles based on the User-id and then load the style Dynamically in the view based on which user is logged-in.
STEP 1: USING USER ID TO CREATE A CSS FILE
<?php
// THIS IS AN ACTION IN YOUR CONTROLLER THAT HANDLES THE PROCESSING OF THE
// USER-SETTINGS FORM...
public function saveUserSetting(Request $request){
// OBTAIN THE $userID YOUR WAY...
$userDataPath = __DIR__ . "/../../../public/css/user_data";
// BUILD THE CSS TO BE ADDED TO USERS CUSTOM CSS FILE
// BASED ON HIS SETTINGS...
// $customizer = //<== GET THE $customizer OBJECT
$css = "button.submitform:hover, button.submitform:focus\{\n";
$css .= "background: " . $customizer->global_‌​lite_colorcode . " !important;\n";
$css .= "\}\n"
// IF USER-SPECIFIC CSS FILE DOES NOT EXIST, WE CREATE IT,
// OTHERWISE WE JUST GET ITS CONTENT AND APPEND NEW STYLES TO IT..
if(!file_exists($userDataPath . "/user_{$userID}.css")){
file_put_contents($userDataPath . "/user_{$userID}.css", $css);
}else{
$data = file_get_contents($userDataPath . "/user_{$userID}.css");
if(!stristr($data, $css) ){$data.= $css;}
file_put_contents($userDataPath . "/user_{$userID}.css", $data);
}
// DO OTHER THINGS...
}
Then on the View, make sure you have created a section called "stylesheets" (for example) in your Master-File (That is; if you are using Template inheritance). Your Main Layout File would contain something like below within the < head > section.
#yield("stylesheets")
Then on the actual View File, you can dynamically add the User's Custom Style-Sheet based on the ID of the logged-in User like so:
#extends('layouts.app')
#section('stylesheets')
<link type="text/css" rel="stylesheet" media="all" href="{{ URL::asset('css/bootstrap.min.css') }}" />
<!-- THIS WILL LOAD ONLY THE USER'S CUSTOM CSS -->
<link type="text/css" rel="stylesheet" media="all" href="{{ URL::asset('css/user_data/user_' . $userID . ".css") }}" />
#endsection
However; it is important to note that in this approach, the data has to first be saved and written to File before you can see any changes... you wouldn't have an instant response of seeing your style applied immediately. If you need such Functionality, you may consider integrating Javascript.
Another way would be to gather all the Front-End Settings that the User specified in the Form, and store them as part of the users Table like under the column_name settings in either serialized or json_encoded format. This means that, once you fetch the Logged-in User Information, you can generate a CSS using the information stored in the settings....

This for sure can be done in an external file, but it won't be an external .css file; it will be a .blade.php file that contains any css styling, similar to the way you're doing it above. The issue is that since the property global_lite_colorcode is attached to a php variable $customizer, it cannot be parsed in a plain .css file.
On your view file, include a <style> tag the same way you are currently doing, and use the #include() blade command to pull in an external php file:
<style>
#include("views.custom.themes")
</style>
Specify a valid path to a .blade.php file using . notation, and in that file, include your "pseudo-inline" css:
button.submitform:hover, button.submitform:focus {
background: {{ $customizer->global_lite_colorcode}} !important;
}
<!-- Any other style tags that rely on php variables -->
As long as $customizer is accessible in the view file that calls the #include function, the code in the included file can also access it.
This is a bit of workaround to using an external .css file, but should work for your needs.

Related

Using Laravel bootstrap css to style only a section of a page

I'm trying to use the default bootstrap css (app.css) that ships with Laravel to style a section of my page - specifically, the form section of my registration page.
I don't want to include app.css in my html header as it gives me undesired effect on other parts of the page. So I want it to style only my html forms within the page.
Currently, I've used either the asset() or HTML::style() methods like this within my form section:
#section('form')
<style> #import "{{ asset('css/app.css') }}"; </style>
<form>...</form>
#endsection
OR
#section('form')
{{ HTML::style('css/app.css') }}
<form>...</form>
#endsection
Both method loads the style correctly, but affects the entire page instead of only the form elements.
I tried using the ViewComposer class to solve this problem by setting a variable in ViewComposer to my desired style - returning it only when I request the required view:
class ViewComposer
{
public function compose(View $view)
{
$data = [];
switch($view->getName())
{
...
case 'sections.register':
$this->data = ['style'=>"<style> #import \"". asset('css/app.css') . "\"; </style>"];
break;
}
return $view->with($this->data);
}
}
However, when I render the sections.register sub-view, I get the style variable like this:
#section('form')
{{ $style ?? '' }}
<form>...</form>
#endsection
the output on the browser is not parsed as css but displayed as-is:
<style> #import "{{ asset('css/app.css') }}"; </style>
So, is there a way I can parse external css for only a given view section within the html page and can it be achieved using the ViewComposer class?
UPDATE:
I was trying a few things and used this:
#section('form')
{!! $style ?? '' !!}
<form>...</form>
#endsection
The css is parsed but still applied to the entire page. I still need it applied to only the form section.
1. One option is to copy only the css you need and paste it into custom css and make a different layout for that view. But that can be tedious work as you said.
2. Another option is to prefix you app.css file. There is a software that can do that here is the tutorial. So if you prefix whole css file with for example: .laravel-app then you can wrap anything that you would like to be styled by app.css like this:
<div class="laravel-app">
<!-- Everything in here will be styled by app.css -->
</div>
This will help you in the long run with your project.
First of all, importing or loading css per-view will be bad for the performance of the application. So, using View Composer to load in css is not advisable. I took a cue from Denis Ćerić's answer, though it wasn't clear at first glance.
Also, the accepted answer on this post made things a little clearer.
The right way to achieve this is to use a css preprocessor. Popular ones are less and sass. I used sass because it is currently adopted by Laravel.
I installed sass on my windows machine following the instructions here.
Create a new scss file: app-custom.scss in the same folder as app.css.
Modify app-custom.scss using nested imports:
.app-form
{
#import 'app';
}
Generate app-custom.css using the sass command on Windows command line:
sass app-custom.scss app-custom.css
Change the class of your form to app-form:
#section('form')
<form class='app-form'>...</form>
#endsection
Include app-custom.css in your header using link tag:
<head>
<link href="{{ asset('css/app-custom.css') }}" rel="stylesheet">
</head>
and you are done.
HINT: if you want to use the style in app.css for multiple separate sections of your page, you can still achieve this from a single scss file. Just include the classes of each section in your scss file like this:
.section-1, .section-2, .section-3
{
#import 'app';
}

Passing data to dynamic CSS file?

This is more a question of what browsers will do, rather than the back-end architecture.
I am using codeigniter and have a controller setup to handle assets (CSS, JS, and images), and at the moment I am simply processing the PHP out of CSS files and presenting them as CSS files to the browser, so www.mysite.com/asset/home.css will call the asset class and generate the CSS file for home from a single file.
I would like to make the request for the CSS files more dynamic, so that the request will determine multiple files that should be combined, and then passed to less.php for parsing and minimization.
Taking into account issues of caching, what would be the best method of passing variables to the CSS class? Flat Link URI variables? Traditional GET URI? I could use a database to reference a given name for its components, but isn't that a lot of overhead?
Any thoughts or opinions are welcomed!
++ How would browsers handle something like standard.menu.comments.css?
+++ I ended up going with a URI string appended to the file. It's not as clean I would want, but it appears to be working. I will likely move to a flat slash separated URI parser soon to clean up the request lines. Thanks for your help!
You can create a file style.php with the following header:
<?php header("Content-type: text/css"); ?>
And link this style in your template:
<link rel="stylesheet" type="text/css" media="screen" href="style.php?color=red">
Then you can import some stylesheets in your style.php:
#import ("someStyle.css");
Or you can pass some $_GET variables and create conditional styles:
<?php
if ($_GET['color'] == 'red')
{
echo ".myBlock {background: #ff0000;}";
}
else
{
echo ".myBlock {background: #00ff00;}";
}
?>
If you just don't want your .css files to be cached, append random $_GET variable to your linked style:
<link rel="stylesheet" type="text/css" media="screen" href="style.css?<?php echo time(); ?>">

Passing extra scripts from view to header

So I'm basically trying to pass the <link> and <script> tags into my original header file from a modules view file (which is displayed in the body of the page). How can I pass variables that include these references?
Currently I have just put extra <head></head> tags into my module's view, but it just feels messy and dodgy to do so, as that means the head tags are used up the top of the page, and also mid-way down.
Edit: Didn't realise that stack overflow edited out my tags that are crucial to this question! Sorry guys!
It sounds like you are really in need of a Template setup for CodeIgniter. Here are links to some of my favorites:
http://williamsconcepts.com/ci/codeigniter/libraries/template/reference.html
http://philsturgeon.co.uk/demos/codeigniter-template/user_guide/
And my personal favorite for simplicity:
http://maestric.com/doc/php/codeigniter_template
EDIT:
Per #Sneaksta's question, here is how I add css scripts to my template:
In my master template I have this code:
<?php if (!empty($cssFiles)): ?>
<?php foreach ($cssFiles as $styleSheet): ?>
<link rel="stylesheet" media="screen" href="<?= base_url(); ?>styles/<?= $styleSheet; ?>" />
<?php endforeach; ?>
<?php endif; ?>
Then in my controllers that might need to load different CSS files per function I do this:
$cssFiles = array('style1.css', 'style2.css', 'style3.css');
$this->template->set('cssFiles', $cssFiles);
Sneaksta,
I think I understand what you are asking about, but I am not 100% sure because you don't have any code examples posted.
So I will give you an example of how you can have a "telescoping" View that allows you to modularly load different style tags inside the head tags.
As Damien Pirsy mentioned, Views are buffered, which means that CI makes a special output buffer and will concatenate a series of View objects together, and then output the final buffer content as a finished web page.
My example below is built on this sort of chain of thinking:
End User
(calls) --> Page Controller, which then:
(calls & passes params) --> Base View
(calls multiple fragment views) --> Fragment View +
--> Fragment View +
--> Fragment View = Final Cumulative Page --> (sent back as output ) --> End User
First make the "base View", which we will call "base.php" for reference sake:
<!doctype html>
<html>
<head>
<!-- Base View -->
<?php
//This "if" + "isset()" statement is important,
// because if you forget to pass the variable in the controller
// CI will throw an error.
// Also important: the name of variable ($style) MUST match the
// the name of the associative element in the controller! (See
// remarks below on handling this in the controller)
if(isset($style))
{
//Loading views is like a telescoping effect:
//A view may load other views into itself recursively
$this->load->view($style);
}
else
{
//This echo statement will show a comment in
// source code if an error occurred during loading a view
echo "<!-- Style not found -->");
}
?>
</head>
<body>
<!-- Page Content Here -->
</body>
</html>
Next you create the Style View (note: the following code fragment would be in a separate file all by itself) which we will call "style1.php", and must located with your other views in order for CI to find it, e.g. inside the "application/views" folder. This lets you swap out an inline style block declared in the header by just changing which style view is loaded:
<style type="text/css">
/*Style 1:*/
/*Just do something simple and obvious, i.e. turn text red*/
body { color: red; }
</style>
Next you create the alternate Style View (note: the following code fragment would be in a separate file all by itself) which we will call "style2.php", and must located with your other views in order for CI to find it, e.g. inside the "application/views" folder. This lets you swap out an inline style block declared in the header by just changing which style view is loaded:
<style type="text/css">
/*Style 2:*/
/*Just do something simple and obvious, i.e. turn text blue*/
body { color: blue; }
</style>
Now inside of our controller "example.php" we tell base.php to load the style1.php file into its header. We do this by passing the file name as a parameter when we load the base.php view, by passing the file name as an element of an associative array, code igniter will parse that parameter array and create a variable with the same name as the associative element, and make that variable available to you inside the base.php view:
<?php
class Example extends CI_Controller
{
//Constructor
function __construct(){ parent::__construct(); }
//Base View request handler
function baseview()
{
//Note: Make an array, be certain to name the element
// the same as what will be expected inside base.php
$params = array("style" => "style1.php");
//Switching to load a different style is now easy
// just comment out the line above, and uncomment the line below:
//$params = array("style" => "style2.php");
//Pass the parameters array into the CI load view method:
$this->load->view("base.php", $params);
}
}
?>
The cumulative result should be the modular ability to switch the style tags inside the page header, by just specifying which "style view" to load (you could even build a model that retrieves which "style views" to load from a database table). Obviously this approach has certain processing overhead constraints inside of a web browser, as you are constructing actual inline HTML source code, rather than linking to a CSS file through a link tag. This means that the browser will not cache the css content for each page load, but will have to download it on each subsequent request.

Change css class with php multi pages

I have a multiple pages website where I wan't to change some css stuffs.
So my index.php?p=page points to various pages but on every page I also want to adjust some css like the color of the currently active menu item(li) etc.
What is the best way to achieve this? Should i just make a php var on each page?
One way to handle this is to put a class on the BODY tag for each page, then make different subclasses for the stuff that changes. This way you don't need to feed in any variables from PHP. It's all done via CSS.
<body class="pageOne">
CSS:
.pageOne h1 {
color:#ff0000
}
.pageTwo h1 {
color:#000000
}
You should have the CSS on an external file, and link it using a <link> tag, like so:
<link rel="stylesheet" type="text/css" href="path_to_stylesheet.css">

Cakephp, dynamically write variables into css file upon load of view?

I'm working out a process to save actions that occur from jquery in my view in cakephp.. I figure an easy way to load the saved values, such as the width and height for a DIV, would be to have cakephp echo a variable as their width / height in the css file, much the same way it would do this in the view file.. I guess I'm not sure exactly where to look for info on this, if its in the cakephp cookbook I guess I'm missing it as I don't see how to do it in there.. any advice is appreciated.
This is actually pretty easy (and powerful), and can be done without the aid of CakePHP.
First, make a new file in your webroot called css.php. At the top of that file put the following:
<?php header("Content-Type: text/css"); ?>
Now, link to this file in the head of your layout, just as you would a normal CSS file.
<link rel="stylesheet" href="/path/css.php" type="text/css" />
And there you have it, a dynamic CSS file. You can pass information to it like so:
<link rel="stylesheet" href="/path/css.php?c=red&fw=700" type="text/css" />
CLARIFICATION: To access the variables mentioned above, you would use the $_GET variable in the CSS file. Take a look at the link tag above. To access those variables in the css file, you would do something like this:
.class {color:<?php echo $_GET['c']; ?>;font-weight:<?php echo $_GET['fw']; ?>;}
UPDATE: After viewing the link you posted about the CakePHP HTML Helper, I realized that there is a better way to do this if you intend to pass a lot of variables to the css file.
Create a new model and controller called DynamicStyle and DynamicStylesController (or something similar). Then, make a new layout file called css.ctp that all of this controller's views will use. Declare the content-type header statement in that layout file.
The last step would be to link to a method in that controller from the head of your standard layout header.
Now you could make a database table of css rules and use those with the HTML helper in the css view.
I just realized CakePHP has something for this as well:
http://book.cakephp.org/view/1440/style
So this may come in handy for anyone who comes across this in the future

Categories