I am developing a WordPress plugin which I would like it to add some predefined CSS to a stylesheet when someone enables a feature.
I cannot simply include the stylesheet in addition to the regular stylesheet because some features will conflict with it. I would like it so that when they click one element it loads only the CSS relevant to this.
When they select this element it should "print" the relevant CSS into a stylesheet.
Can I call a function that I created which contains CSS and gets called only once the feature is enabled?
There are a couple ways I would approach this.
You can use use inline css and not require the theme's style sheet. And write what you need between your conditions, like this the first example or use wp_add_inline_style.
IDEA 1: not using wp_add_inline_style
//* Load CSS
function yourplugin_prefix_load_css() {
add_action( 'wp_head', 'yourpluginprefix_css', 15 );
}
add_action( 'plugins_loaded' , 'yourplugin_prefix_load_css' );
//* CSS
function yourpluginprefix_css() {
//vars
$a = get_option( 'where_a', 'what_a' );
$b = get_option( 'where_b', 'what_b' );
// begin CSS
$css = '';
$css .= '<style class="whatever" >';
//condition $a
if ( $a == '0' ) :
$css .= '
.property{
display: inline-block;
}
';
endif; //condition for $a
//condition $b
if ( $b != '1' ) :
$css .= '
.property-something{
border: 1px solid #333;
}
';
endif; //condition for $b
//close the style sheet
$css .= '</style>';
//minify it
$css_min = str_replace( array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $css );
echo $css_min;
}
IDEA 2 with wp_add_inline_style
Alternatively, you can use wp_add_inline_style and get the current theme's handle .
function pluginprefix_css() {
//get current theme stylesheet handle
$current_theme = ( wp_get_theme() );
//get our values for conditions
$a = get_option( 'where_a', 'what_a' );
$b = get_option( 'where_b', 'what_b' );
//begin css
$css = '';
//condition $a
if ( $a == '0' ) :
$css .= '
.property{
display: inline-block;
}
';
endif; //condition for $a
//condition $b
if ( $b != '1' ) :
$css .= '
.property-something{
border: 1px solid #333;
}
';
endif; //condition for $b
//minify css
$css_min = str_replace( array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $css );
//add inline style
wp_add_inline_style( $current_theme->stylesheet, $css_min );
}
add_action( 'wp_enqueue_scripts', 'pluginprefix_css' );
If you need to load library after the site is loaded, your best hope is javascript.
E.g. you can add code snippet into head when click on element. In jQuery
var e = 'button.class';
var remove_css = '#my_style_1';
var code = '<link rel="stylesheet" type="text/css" href="/path/to/css_part.css">';
$(e).on( 'click', function() {
$('head').append( code );
$(remove_css).remove();
});
Replace e variable with class or element which will add code into header on click.
UPDATED: find in source the identificator (ID) of your css file and put it in remove_css variable. It will remove it after element clicked. I should note that this solution is not persistent and lasts until page switch.
--
If you need load css based on option, create an option in your admin, register your styles and then enable it based on option.
Somewhere in code register your style:
wp_register_style( 'my_style_original', '/path/to/css_part.css' );
wp_register_style( 'my_style_replace', '/path/to/css_part.css' );
And then eneable it based on option
$enable_css = get_option( 'enable_css' );
if( $enable_css )
wp_enqueue_style( 'my_style_replace' ); // if setting enabled load second css
else
wp_enqueue_style( 'my_style_original' ); // if setting not enabled load original css
This will load the style only when option 'enable_css' is not false or empty.
To create option page see https://codex.wordpress.org/Creating_Options_Pages or for easier setup you can stick to ACF options (https://www.advancedcustomfields.com/add-ons/options-page/);
You can create a function that writes indented style into the specific element. Remember that this is not considered bad coding, anyway I don't know how it'd be considered since it'd be dynamic content.
So, for example, you have:
<input type="text" />
And when the user clicks to add the style, the function would add:
<input type="text" style="..." />
In the other hand, when the user refreshes the page, the style would disappear.
Create a php function that takes the arguments of what features are enabled to make a custom stylesheet, and dynamically enqueue that stylesheet. Use .htaccess or similar settings to redirect requests for your custom_thingy.css to custom_thingy.php and just have it echo the custom styles, it'll behave like a regular stylesheet.
foreach($style_options as $option) {
echo file_get_contents($option_style_file[$option]);
}
if you using wordpress. you can use wp_add_inline_style
Related
As mentioned in the title. I try to change the image source to a default image, if an image's expiration date is expired.
I used ACF and added a new date field to all media files.
I then created the following function:
function check_expiration_date($post) {
$url = get_the_post_thumbnail_url($post->ID);
$thumbnail_id = get_post_thumbnail_id( $post->ID );
$today = date('d/m/Y');
$expire = get_field('expiration_date', $thumbnail_id);
if( $expire < $today && $expire!="" )
{
$url = "default.jpg";
}
return $url;
}
Now this function works for images that I add sepcifically in template files
but this will not work for images that have been added via the editor on post pages.
I tried to to use various hooks to change the html markup first before attempting to get the meta information but none of those had any effect on the outcome. Here an example:
function change_image_markup($html, $id, $caption, $title, $align, $url) {
$html5 = "<section>";
$html5 .= "<figure id='post-$id media-$id' class='align-$align'>";
$html5 .= "<img src='$url' alt='$title' />";
if ($caption) {
$html5 .= "<figcaption>$caption</figcaption>";
}
$html5 .= "</figure>";
$html5 .= "<section>";
return $html5;
}
add_filter( 'image_send_to_editor', 'change_image_markup', 10, 9 );
Is there a specific hook that can alter the html markup of images?
I am using Wordpress 5.5.1
any hint or tip is appreciated.
As the question is a month old and I did not receive any answers, I figured I would answer my own question. There is a difference in the requirements though. Instead of changing the image to a default one, I removed the image completely. Both can be achieved though.
So there was no real hook that could me out, as those hooks only call the action when actually inserting the image.
In my case everytime the post is being loaded the images had to be checked if they are expired or not.
Instead of working with hooks I created my own function and call that function inside single.php
In the single.php usually there is something like echo post->post_content;
Instead I call my function and give the post content as a value.
add_post_based_on_expiration_date($post->post_content);
And my function looks something like this:
function add_post_based_on_expiration_date($post_content){
$search_pattern = '/<figure(.*)\/figure>/'; //<figure(.*)/figure> /wp-image-(\d+)/
preg_match_all( $search_pattern, $post_content, $embedded_images );
$embedded_images_count = count( $embedded_images[0] );
$new_content = $post_content;
if ( $embedded_images_count > 0 ) {
for ( $i=0; $i < $embedded_images_count ; $i++ ) {
$dom = new DOMDocument;
#$dom->loadHTML($embedded_images[0][$i]);
$image = $dom->getElementsByTagName('img');
$imageId = str_replace("wp-image-" , "" , $image[0]->getAttribute('class'));
if(check_expiration_date_get_by_id($imageId)){
$new_content = str_replace($embedded_images[0][$i],"",$new_content);
}
};
};
echo $new_content;
}
It looks a bit messy but it does it's job. What I do is using regex to look for the image mark up <figure..... and save it in an array. Afterwards by using the DOM class I get the class, which contains the media ID. Then I call my function which is an alteration of the one above in the question. The function just returns true or false depeding on the expiration date. If it is true I remove it from the content and at the end I return it.
Therefore if an image is expired the image markup gets completely removed.
The downside of this aside from the messy code is the processing time. Since it it always called when opening a post site.
I recently have removed the excerpt function from Wordpress and made my own so I can allow some HTML to be shown in the excerpt. I made the changes in a child theme functions file.
It was working fine on the front-end but after that I had problems on the back-end of Wordpress. In /wp-admin/edit.php in an excerpt of posts I get the post excerpt with all the HTML tags so it was really hard to read the actual content of post.
To fix that I did a change in the Wordpress core file /wp-admin/includes/class-wp-posts-list-table.php.
I removed content from line 1037.
echo esc_html( get_the_excerpt() );
the function esc_html
How can I make this change permanent so that after a possible update of Wordpress, the change will not be lost?
Is this change safe? I will have a lot of users in my back-end of Wordpress.
UPDATE MY QUESTION
add_filter( 'get_the_excerpt', 'my_clean_excerpt' );
function wpse_allowedtags() {
// Add custom tags to this string
return '<style>,<br>,<em>,<i>,<ul>,<ol>,<li>,<a>,<p>,<img>,<video>,<audio>,<div>,<wbr>';
}
if ( ! function_exists( 'wpse_custom_wp_trim_excerpt' ) ) :
function wpse_custom_wp_trim_excerpt($wpse_excerpt) {
$raw_excerpt = $wpse_excerpt;
if ( '' == $wpse_excerpt ) {
$wpse_excerpt = get_the_content('');
$wpse_excerpt = strip_shortcodes( $wpse_excerpt );
$wpse_excerpt = apply_filters('the_content', $wpse_excerpt);
$wpse_excerpt = str_replace(']]>', ']]>', $wpse_excerpt);
//$wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags()); /*IF you need to allow just certain tags. Delete if all tags are allowed */
//Set the excerpt word count and only break after sentence is complete.
$excerpt_word_count = 75;
$excerpt_length = apply_filters('excerpt_length', $excerpt_word_count);
$tokens = array();
$excerptOutput = '';
$count = 0;
// Divide the string into tokens; HTML tags, or words, followed by any whitespace
preg_match_all('/(<[^>]+>|[^<>\s]+)\s*/u', $wpse_excerpt, $tokens);
foreach ($tokens[0] as $token) {
if ($count >= $excerpt_length && preg_match('/[\,\;\?\.\!]\s*$/uS', $token)) {
// Limit reached, continue until , ; ? . or ! occur at the end
$excerptOutput .= trim($token);
break;
}
// Add words to complete sentence
$count++;
// Append what's left of the token
$excerptOutput .= $token;
}
$wpse_excerpt = trim(force_balance_tags($excerptOutput));
$excerpt_end = ' ' . ' » ' . sprintf(__( 'Read more about: %s »', 'wpse' ), get_the_title()) . '';
$excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);
//$pos = strrpos($wpse_excerpt, '</');
//if ($pos !== false)
// Inside last HTML tag
//$wpse_excerpt = substr_replace($wpse_excerpt, $excerpt_end, $pos, 0); /* Add read more next to last word */
//else
// After the content
//$wpse_excerpt .= $excerpt_more; /*Add read more in new paragraph */
// Extra filter to remove the above text from excerpt
$badwords = array(
'< !DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">',
'< ?xml encoding="utf-8" ?>',
);
foreach ( $badwords as $badword ) {
$wpse_excerpt = str_replace( $badword, '', $wpse_excerpt);
}
//End extra filrer
return $wpse_excerpt;
}
return apply_filters('wpse_custom_wp_trim_excerpt', $wpse_excerpt, $raw_excerpt);
}
endif;
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse_custom_wp_trim_excerpt');
I used this function to add html tags in excerpt.
I after updated the excerpts in database. And i get the result that i wanted.
But i get this in backend.
problem backend
So a fast way to get away with the problem was to go to /wp-admin/includes/class-wp-posts-list-table.php and remove the function esc_html from this line echo esc_html( get_the_excerpt() ); where the excerpt is generated for back-end.
So my question is not about how to allow html tags in excerpt, I already did that, but how to make that change permanent.
My back-end after that change. Back-end after
That is what i want to do.
Don't ever change WP core... You'll lose the ability to update it and your system will be vulnerable.
You can create plugins to change the excerpt behavior, you can create your own functions and use it in your theme templates...
There is a lot of ways better than to t
Never change the core of the WordPress. As Artur Luiz Oliveira mentioned you will lose those changes the first time WordPress will update, and you should be aware that it will do that automatically once the version becomes very dated if you like it or not.
To do what you are looking for I would suggest you look into this question.
Might be more coding involved but this will stick and won't be affected when the WordPress version updates.
I am having trouble preloading CSS on my WordPress site. I was writing a script to find every JS and CSS script enqueued in the footer, and preload it in the <head>. The code for the JS scripts works fine (when I go to page source on the site, I can see the <link> tags with the preload attribute inside), but the CSS preload link tags aren't showing up.
It is very likely I am doing this completely wrong, as I found working code for the JS scripts and then tried to alter it to get it to work for the CSS. For instance, I don't think the version appendage applies to CSS, but I assumed it would still work since it would default to false, right?
As a related question, I am having the same issue with webfonts. Google Pageview Insights is telling me to preload webfonts, so I added some php to do that, but when I run pageview insights again, no dice.
Here is the code:
add_action('wp_head', function () {
global $wp_scripts;
global $wp_styles;
foreach($wp_scripts->queue as $handle) {
$script = $wp_scripts->registered[$handle];
//-- Check if script is being enqueued in the footer.
if($script->extra['group'] === 1) {
//-- If version is set, append to end of source.
$source = $script->src . ($script->ver ? "?ver={$script->ver}" : "");
//-- Spit out the tag.
echo "<link rel='preload' href='{$source}' as='script'/>\n";
}
}
foreach($wp_styles->queue as $handle) {
$style = $wp_styles->registered[$handle];
if ($style->extra['group'] === 1) {
$source = $style->src . ($style->ver ? "?ver={$style->ver}" : "");
echo "<link rel='preload' href='{$source}' as='style' onload='this.rel = \"stylesheet\"'/>\n
<noscript><link rel='stylesheet' href='{$source}'/></noscript>\n";
}
}
//This is the code to preload webfonts
echo "<link rel='preload' href='/wp-content/themes/salient/css/fonts/fontawesome-webfont.woff?v=4.2' as='font' type='font/woff'>";
echo "<link rel='preload' href='/wp-content/themes/salient/css/fonts/fontawesome-webfont.ttf?v=4.2' as='font' type='font/ttf'>";
}, 1);
Welcome to StackOverflow!
A function that I have used in my projects for preloading CSS effectively is:
function add_rel_preload($html, $handle, $href, $media) {
if (is_admin())
return $html;
$html = <<<EOT
<link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'"
id='$handle' href='$href' type='text/css' media='all' />
EOT;
return $html;
}
add_filter( 'style_loader_tag', 'add_rel_preload', 10, 4 );
A similar function could in theory be used for JS and Webfonts, but this has only been tested with CSS.
Hope this is helpful!
The exact code, which has worked for me:
function preload_for_css ( $html, $handle, $href, $media ) {
if ( is_admin () )
{
return $html;
}
echo '<link rel="stylesheet preload" as="style" href="' . $href . '" media="all">';
}
add_filter ( 'style_loader_tag', 'preload_for_css', 10, 4 );
It will pass GTmetrix and Google Insights test. At least passed for me :-)
I am busy with the Customizer from WordPress and that is working fine i only getting the output of the css in the style tags (inline) and i want it in the customizer.css file.
Does somebody know how i can add the CSS into the customizer.css?
<?php
function customizerCSS() {
wp_enqueue_style('custom-style', get_template_directory_uri() . '/customizer.css');
$color = fw_get_db_customizer_option('body_background');
$custom_css = '
html, body {
background-color : ' . $color . ';
}';
wp_add_inline_style('custom-style', $custom_css );
}
add_action( 'wp_enqueue_scripts', 'customizerCSS' );
?>
You can use file_get_contents for getting all css written in the customizer.css file and file_put_contents for adding new css rules into customizer.css file.
Your code will be:
function customizerCSS() {
$color = fw_get_db_customizer_option('body_background');
$custom_css = '
html, body {
background-color : ' . $color . ';
}';
$file = file_get_contents(TEMPLATEPATH.'/customizer.css');
if (strpos($file, $custom_css) === false) { // for not rewriting file every time, when there is no changes
$file .= $custom_css;
file_put_contents(TEMPLATEPATH.'/customizer.css', $file);
}
wp_enqueue_style('custom-style', get_template_directory_uri() . '/customizer.css');
}
add_action( 'wp_enqueue_scripts', 'customizerCSS' );
We are getting all new css rules from $custom_css, everything from customizer.css and comparing them. If there is new css rules in the $custom_css which aren't exists in the customizer.css stylesheet, then we just writе them into file.
Edit:
Function below will override customizer.css file with values from $custom_css variable every time:
function customizerCSS() {
$color = fw_get_db_customizer_option('body_background');
$custom_css = '
html, body {
background-color : ' . $color . ';
}';
file_put_contents(TEMPLATEPATH.'/customizer.css', $custom_css);
wp_enqueue_style('custom-style', get_template_directory_uri() . '/customizer.css');
}
add_action( 'wp_enqueue_scripts', 'customizerCSS' );
I'm working on a Bootstrap 3 Wordpress theme. To make my images responsive I added Bootstrap's img-responsive class to them with the following code in my functions.php
<?php
function bootstrap_responsive_images( $html ){
$classes = 'img-responsive'; // separated by spaces, e.g. 'img image-link'
// check if there are already classes assigned to the anchor
if ( preg_match('/<img.*? class="/', $html) ) {
$html = preg_replace('/(<img.*? class=".*?)(".*?\/>)/', '$1 ' . $classes . ' $2', $html);
} else {
$html = preg_replace('/(<img.*?)(\/>)/', '$1 class="' . $classes . '" $2', $html);
}
// remove dimensions from images,, does not need it!
$html = preg_replace( '/(width|height)=\"\d*\"\s/', "", $html );
return $html;
}
add_filter( 'the_content','bootstrap_responsive_images',10 );
add_filter( 'post_thumbnail_html', 'bootstrap_responsive_images', 10 );
This works pretty well, all get their class="img-responsive" except the thumbs in galleries. They only hav class="attachment-thumbnail or attachment-medium" depending on te choosen image size.
Any ideas?
Just use the same CSS bootstrap uses for .img-responsive and create a selector for your image galleries and apply that CSS to your new selector