Blur <header> background-image, but not children - javascript

I recently switched over to using Ghost for my blog and by default I'm using the Casper theme. What I'm trying to do is blur the site-head header, by styling the CSS using -webkit-filter: blur, but when I do this, every other element also becomes blurred.
I've tried adding custom style attributes to each other element like -webkit-filter: blur(0px) !important in an effort to override the site-head blur, but nothing changes. I've also tried adding and blurring a separate element in between the header and the start of the first div leading into the other elements, but this ended in the same result.
I'm pretty new to CSS and Javascript and can't help but think I'm just completely overlooking something here.
This is the index.hbs:
<header class="site-head" {{#if #blog.cover}}style="background-image: url({{#blog.cover}})"{{/if}}>
<div class="vertical">
<div class="site-head-content inner">
{{#if #blog.logo}}<a class="blog-logo" href="{{#blog.url}}"><img src="{{#blog.logo}}" alt="Blog Logo" /></a>{{/if}}
<h1 class="blog-title">{{#blog.title}}</h1>
<h2 class="blog-description">{{#blog.description}}</h2>
</div>
</div>
</header>
And here is the style for the site-head:
.site-head {
position: relative;
display: table;
width: 100%;
height: 60%;
margin-bottom: 5rem;
text-align: center;
color: #fff;
background: #303538 no-repeat center center;
background-size: cover;
}

Related

Can this be achieved without js?

I have this image gallery which I want to do without the javascript. Can this be done without using the javascript ?? Just need the big picture to change when mouseover or something similar.
function myFunction(imgs) {
var expandImg = document.getElementById('expandedImg')
var imgText = document.getElementById('imgtext')
expandImg.src = imgs.src
imgText.innerHTML = imgs.alt
expandImg.parentElement.style.display = 'block'
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
/* The grid: Four equal columns that floats next to each other */
.column {
float: left;
width: 25%;
padding: 10px;
}
/* Style the images inside the grid */
.column img {
opacity: 0.8;
cursor: pointer;
}
.column img:hover {
opacity: 1;
}
/* Clear floats after the columns */
.row:after {
content: '';
display: table;
clear: both;
}
/* The expanding image container */
.container {
position: relative;
display: none;
}
/* Expanding image text */
#imgtext {
position: absolute;
bottom: 15px;
left: 15px;
color: white;
font-size: 20px;
}
/* Closable button inside the expanded image */
.closebtn {
position: absolute;
top: 10px;
right: 15px;
color: white;
font-size: 35px;
cursor: pointer;
}
<div style="text-align: center">
<h2>Tabbed Image Gallery</h2>
<p>Click on the images below:</p>
</div>
<!-- The four columns -->
<div class="row">
<div class="column">
<img src="img_nature.jpg" alt="Nature" style="width: 100%" onclick="myFunction(this);" />
</div>
<div class="column">
<img src="img_snow.jpg" alt="Snow" style="width: 100%" onclick="myFunction(this);" />
</div>
<div class="column">
<img src="img_mountains.jpg" alt="Mountains" style="width: 100%" onclick="myFunction(this);" />
</div>
<div class="column">
<img src="img_lights.jpg" alt="Lights" style="width: 100%" onclick="myFunction(this);" />
</div>
</div>
<div class="container">
<span onclick="this.parentElement.style.display='none'" class="closebtn">×</span
>
<img id="expandedImg" style="width: 100%" />
<div id="imgtext"></div>
</div>
Any help is appreciated. Sorry for adding this text as StackOverflow won't let me post this without adding more text.
Thanks in advance.
Preface
Though not impossible, I nonetheless highly recommend using JavaScript instead of CSS for this task. You should not see the following content of this answer as an alternative to JavaScript's intended purpose, but see this as a playful "solution".
Another big point to use JavaScript instead of CSS is: Using CSS for this task is not accessible at all. You should always strive to make good, easy-to-use and accessible websites.
You should especially refrain from using this in a business environment for the aforementioned reason.
CSS-only solution
Necessary HTML changes
Since CSS is cascading, the image-previews need to come before either the big image itself or its ancestor. You can imagine this like this: The HTML is a tree, and effects are only carried through down to the leaves, but cannot affect neighbouring branches as that would require backtracking at some point.
In code, this could look like this:
<!-- Either this (case 1): -->
<img class="img-preview">
<img class="big-img">
<!-- Or this (case 2): -->
<img class="img-preview">
<div>
<img class="big-img"> <!-- May be nested deeper -->
</div>
The CSS
The CSS should be relatively simple. The only issue is, that for each image-preview, a new CSS-rule needs to be added. This makes adding a new image-preview a bit more work in the future, but more importantly: It crams your CSS full with unnecessary rules! This will probably result in unused CSS-rules in case you'll rewrite some, and will hinder maintenance and readability heavily.
Friendly reminder: This should better be done by using JavaScript!
CSS' :hover-pseudo-class is effectively the same as JS' mouseover. Using this and the general sibling-combinator ~ (and potentially the descendant combinator ), we can override the big image's background-image-property depending on the image-preview that is hovered:
/* Either this (case 1): */
.img-preview:hover~.big-img {/* ... */}
/* Or this (case 2): */
.img-preview:hover~* .big-img {/* ... */}
As I have already mentioned, every image-preview requires its own CSS-rule. This is because CSS cannot use HTML-attributes for its properties (except for pseudo-elements and their content-property, I think).
This means, the CSS could look like this for the current HTML:
/* The CSS */
.img-preview[data-src="https://picsum.photos/id/10/64/64"]:hover~.big-img {
background-image: url("https://picsum.photos/id/10/64/64");
}
.img-preview[data-src="https://picsum.photos/id/1002/64/64"]:hover~.big-img {
background-image: url("https://picsum.photos/id/1002/64/64");
}
/* etc. */
/* Ignore; for styling only */
img {border: 1px solid black}
.img-preview {
width: 2rem;
height: 2rem;
}
.big-img {
width: 4rem;
height: 4rem;
}
<img class="img-preview"
src="https://picsum.photos/id/10/32/32"
data-src="https://picsum.photos/id/10/64/64">
<img class="img-preview"
src="https://picsum.photos/id/1002/32/32"
data-src="https://picsum.photos/id/1002/64/64">
<!-- etc. -->
<img class="big-img">
(Sidenote: I used attribute-selectors here, but the same thing could be done using IDs or similar, as long as every image-preview can be selected individually.)
Endnote
Adding text-descriptions while hovering may be solved in a similar fashion, but is left as a task.
Unfortunately, the big image won't stay when using this approach. If you want it to stay, you should take a look at Abd Elbeltaji's answer. They use <input>- and <label>-tags to accomplish that, together with CSS' :checked-pseudo-class.
Despite looking so, changing the HTML as shown does not restrict you in how you can style your elements, especially when using FlexBox or CSS Grid. Not only do they make styling easier, they are also meant to easily make a website responsive.
Accessibility
Again: This is not an accessible solution! This whole task should certainly be handled by JavaScript.
Should this be a public website, then I advise adding alt-descriptions for every image, even the previews. Unfortunately updating the big image's alt-attribute via CSS is impossible, making it inaccessible, which in turn harms your SEO. This being said, I commend your effort in displaying the image's alt-attribute in your original code, though not perfect. You might want to take a look at <figure>.
While we're at it: I'd also advise learning some semantic HTML-tags for the purpose of accessibility.
Pseudo-elements (::after, ::before, etc.) are also inaccessible. You should not use them to contain any relevant information/text. Though they may be used for styling-purposes in every imaginable way.
Yes, you can achieve the same behavior without the use of javascript, you may use the concept of input elements (checkbox for single toggle value, radio for multiple select values) as adjacent siblings to your elements that they should be affected of the input, and by utilizing the :checked pseudo selector for inputs in css, in a compination with the adjacent sibling selector ~ you can affect the desired elements when the input is checked. You can also use labels which will allow you to hide your inputs and trigger their values with whatever is inside your label.
// No JS!
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
/* The grid: Four equal columns that floats next to each other */
.column {
float: left;
width: 25%;
padding: 10px;
}
/* Style the images inside the grid */
.column img {
opacity: 0.8;
cursor: pointer;
}
.column img:hover {
opacity: 1;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The expanding image container */
.container {
position: relative;
}
/* Expanding image text */
#imgtext::after {
position: absolute;
bottom: 15px;
left: 15px;
color: white;
font-size: 20px;
}
/* Closable button inside the expanded image */
.closebtn {
position: absolute;
top: 10px;
right: 15px;
color: white;
font-size: 35px;
cursor: pointer;
}
.container .img {
height: 500px;
width: 100%;
background-image: url(https://images.pexels.com/photos/15286/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940);
background-size: cover;
}
/* Tab select */
input[name=tabSelect],
#hideImage {
display: none;
}
#tabSelect1:checked~div.container .img {
background-image: url(https://images.pexels.com/photos/15286/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940);
}
#tabSelect2:checked~div.container .img {
background-image: url(https://images.pexels.com/photos/869258/pexels-photo-869258.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940);
}
#tabSelect3:checked~div.container .img {
background-image: url(https://images.pexels.com/photos/1183021/pexels-photo-1183021.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940);
}
#tabSelect4:checked~div.container .img {
background-image: url(https://images.pexels.com/photos/1124960/pexels-photo-1124960.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940);
}
#tabSelect1:checked~div.container #imgtext::after {
content: "Nature";
}
#tabSelect2:checked~div.container #imgtext::after {
content: "Snow";
}
#tabSelect3:checked~div.container #imgtext::after {
content: "Mountains";
}
#tabSelect4:checked~div.container #imgtext::after {
content: "Lights";
}
/* image hide btn */
#hideImage:checked~div.container {
display: none;
}
<div style="text-align:center">
<h2>Tabbed Image Gallery</h2>
<p>Click on the images below:</p>
</div>
<input type="radio" name="tabSelect" id="tabSelect1">
<input type="radio" name="tabSelect" id="tabSelect2">
<input type="radio" name="tabSelect" id="tabSelect3">
<input type="radio" name="tabSelect" id="tabSelect4">
<!-- The four columns -->
<div class="row">
<div class="column">
<label for="tabSelect1">
<img src="https://images.pexels.com/photos/15286/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Nature" style="width:100%">
</label>
</div>
<div class="column">
<label for="tabSelect2">
<img src="https://images.pexels.com/photos/869258/pexels-photo-869258.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Snow" style="width:100%">
</label>
</div>
<div class="column">
<label for="tabSelect3">
<img src="https://images.pexels.com/photos/1183021/pexels-photo-1183021.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Mountains" style="width:100%">
</label>
</div>
<div class="column">
<label for="tabSelect4">
<img src="https://images.pexels.com/photos/1124960/pexels-photo-1124960.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Lights" style="width:100%">
</label>
</div>
</div>
<input type="checkbox" id="hideImage">
<div class="container">
<label for="hideImage" class="closebtn">×</label>
<div class="img"></div>
<div id="imgtext"></div>
</div>
Here is a working example in: JSFiddle
Note! this approach is not optimal and would be tricky to expand in case you need to add more values.
PS: I had to change the images since the ones provided in your code do not exist.

Draw <svg> or <canvas> after headline [html, js]

I have a cool design and try to transfer it to a website.
What I want is basically shown on the picture below. I want a shape behind headlines.
I've seen a canvas solution once on a template, but I don't know how they did it.
Obviously I can’t use simple background-image, because the headlines are different long/ height.
So my idea is to grab the SVG.js – library ( svgjs.dev ) or something similar and put a foreach js script.
Get headline dimensions and draw a canvas/ SVG. Position the canvas/ SVG via CSS as relative.
Do anyone got an idea? Thank you.
It's possible to achieve this design if you use:
inline-block elements
a background-size style set to 100% (or contains if you don't want it to fit the whole width and height element)
an SVG background image (prettier than bitmaps)
So You could set this style for such elements (background-repeat style seems to be removable):
header, h1, h2 /* whatever... */
{
background-image:url("your_fantastic_resizable_background.svg");
background-size: 100% 100%;
background-repeat:no-repeat;
display: inline-block;
}
Thus, this design is kind of flawed: if two inline-block styled elements follow each in the code flow, the last will be appended next to the first, which is not you probably want. Hence, you'll have to insert between a line-break between:
<header>
<span>Test</span>
<span>For a great logo</span>
</header>
<br/> <!-- sad. -->
<h1>Test 1</h1>
Below a working snippet made with a GNU Head logo (Free Art License 1.3).
header,
h1,
h2,
h3,
h4 {
background-image: url("https://upload.wikimedia.org/wikipedia/commons/2/22/Heckert_GNU_white.svg");
background-size: 100% 100%;
background-repeat: no-repeat; /* seems to be not useful ... */
display: inline-block;
font-family: sans-serif;
color: white;
text-shadow: 0px 0px 3px black;
}
header {
font-size: 4em;
}
header span::after {
content: "\A";
white-space: pre;
}
<header>
<span>Test</span>
<span>For a great logo</span>
</header>
<br/>
<h1>Test 1</h1>
<p>A first very good looking sentence.</p>
<h2>Test 2</h2>
<p>A second very good looking sentence.</p>
<h3>Test 3</h3>
<p>A third very good looking sentence.</p>
<h4>Test 4</h4>
<p>A fourth very good looking sentence.</p>
Thank you, Amessihel, but this is not what I needed.
A background-image with background-size of 100% for a variable height/ length headline-object would look in the end like....not well done.
But somehow you pointed me in the right direction. I mean, I am not super happy with this solution, because it's height-limited - but it's working for now.
I just used the :before and :after selector to split the image how I needed.
<style id="SCSS">
h1, h2 {
position: relative;
background: #087f89;
display: inline-block;
padding: 0 20px 0 23px;
color: whitesmoke;
&:after {
content: "";
position: absolute;
height: 100%;
right: 0;
top: 0;
width: 6px;
background-image: url(https://i.imgur.com/Amv4TJp.png);
background-repeat: no-repeat;
background-position: bottom 0 left 0;
}
&:before {
content: "";
position: absolute;
height: calc(100% + 14px);
width: 30px;
background-image: url(https://i.imgur.com/o9bsJN5.png);
background-repeat: no-repeat;
background-position: bottom 0 left 0;
left: 0;
top: 0;
}
}
</style>
<article class="post-2 page type-page status-publish hentry" id="post-2">
<header class="entry-header">
<h1 class="entry-title">Headline</h1>
</header><!-- .entry-header -->
<div class="entry-content">
<p>This is an example page. It’s different from a blog post because it will stay in one place and will show up
in your site navigation (in most themes). Most people start with an About page that introduces them to
potential site visitors. It might say something like this:</p>
<p>…or something like this:</p>
<p>As a new WordPress user, you should go to your dashboard
to delete this page and create new pages for your content. Have fun!</p>
<h2>Headline as well</h2>
<p>This is an example page. It’s different from a blog post because it will stay in one place and will show up
in your site navigation (in most themes). Most people start with an About page that introduces them to
potential site visitors. It might say something like this:</p>
</div><!-- .entry-content -->
</article>
Here is my fiddle : https://jsfiddle.net/smatplacid/pwaLuzdo/3

Show div when post has class

Update
I'd modded the CSS given by David Thomas a bit. Its now a banner.
.div.popular::before {
/* setting the default styles for
the generated content: */
display: block;
width: 10em;
height: 2em;
line-height: 2em;
text-align: center;
background: #F60;
color: #fff;
font-size: 1.4rem;
position: absolute;
top: 30px;
right: 0px;
z-index: 1;
}
I would like to make a folded corner sort of like in this post: Folded banner using css
--- Original post ---
Let me first explain what I'm trying to do. I'm trying to give some post some extra attention by making a little circle with some call-to-action text in it.
But I only want this to trigger when a div has a specific class.
So if the div the class populair or sale I would like to have a little circle show up on that post. This script what I am using right now.
$(document).ready(function($){
if($("#front-page-items").hasClass('populair')){
$(".populair-div").show();
}
if($("#front-page-items").hasClass('sale')){
$(".sale-div").show();
}
});
And this HTML:
<div class="populair-div" style="display:none;">
<strong>Populair</strong>
</div>
<div class="sale-div" style="display:none;">
<strong>Sale</strong>
</div>
But this only show's the populair-div and not the other one. I'm guessing my script is wrong. Should I use else for all the other call-to-action classes?
$(document).ready(function($){
if($("#front-page-items").hasClass('populair')){
$(".populair-div").show();
}
else($("#front-page-items").hasClass('sale')){
$(".sale-div").show();
}
else($("#front-page-items").hasClass('Free')){
$(".free-div").show();
} // and so on
});
Is there someone that could help me out? Also is it possible to echo the div so I don't have to write a whole div for every call-to-action div?
For something like this, where the displayed text is explicitly linked to the class-name of the element it's easiest to use CSS and the generated content available, effectively hiding the elements you don't wish to show by default and then explicitly allowing elements you want to show, along with the generated content of those elements (using the ::before and ::after pseudo-elements:
div {
/* preventing <div> elements
from showing by default: */
display: none;
}
div.populair-div,
div.sale-div {
/* ensuring that elements matching
the selectors above (<div>
elements with either the 'sale-div'
or 'populair-div' class-names
are shown: */
display: block;
}
div.populair-div::before,
div.sale-div::before {
/* setting the default styles for
the generated content: */
display: block;
width: 4em;
height: 4em;
line-height: 4em;
text-align: center;
border: 3px solid transparent;
border-radius: 50%;
}
div.populair-div::before {
/* setting the text with the
"content" property: */
content: "Popular";
/* providing a specific colour
for the generated contents'
border: */
border-color: #0c0;
}
div.sale-div::before {
content: "Sale";
border-color: #f90;
}
/* entirely irrelevant, just so you can
see a (slightly prettified) difference
should you remove the default display
property for the <div> elements: */
code {
background-color: #ddd;
}
em {
font-style: italic;
}
<div class="neither-popular-nor-sale">
<p>
This element should not be shown, it has neither a class of <code>"populair-div"</code> <em>or</em> <code>"sale-div"</code>.
</p>
</div>
<div class="populair-div">
</div>
<div>Also not to be shown.</div>
<div class="sale-div">
</div>
You can use toggle function for this. It will be shorter and clearer.
Display or hide the matched elements.
Note: The buttons is for tests.
$(document).ready(function($){
init();
});
function init() {
$(".populair-div").toggle($("#front-page-items").hasClass('populair'));
$(".sale-div").toggle($("#front-page-items").hasClass('sale'));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="front-page-items" class="populair sale"></div>
<div class="populair-div">populair-div</div>
<div class="sale-div">sale-div</div>
<hr />
<button onclick="document.getElementById('front-page-items').classList.toggle('populair');init()">toggle populair</button>
<button onclick="document.getElementById('front-page-items').classList.toggle('sale');init()">toggle sale</button>

Preserve visual order of mixed floated elements

JSFiddle : https://jsfiddle.net/ttpkfs9s/
I have a UI component that should arrange elements into a row and displays them with elements on the left and on the right, with the active element being in the middle:
[1][2][3] [4] [5][6][7][8][9]
So far I have been achieving this by floating elements left and right, while keeping the one in the middle float: none; (this is good enough).
However, way too late into implementing the navigation JS I realised that I've made a huge mistake, and that the actual order the elements are displayed in are as follows:
[1][2][3] [4] [9][8][7][6][5]
Which is a huge problem as these elements are supposed to be clickable /facepalm
Are there any at most not too invasive CSS/HTML options I can use to get the displayed order correct?
EDIT: I missed the part about you needing the active div to always be in the center of the row.
You could contain the div's inside a container, and float the container insted, but that would probably be hard to do.
I took the liberty of changing things up abit, maybe you can use it, maybe u can't.
I set all items to the same width, and made a function for resizing the div's after u click one of the items.
https://jsfiddle.net/ttpkfs9s/1/
html
<div class="row">
<div class="item left">1</div>
<div class="item left">2</div>
<div class="item left">3</div>
<div class="item left">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
css
.row {
height: 150px;
background: blue;
width: 100%;
}
.item {
float: left;
padding: 2.5px;
color: white;
width: 9.4%;
height: 100%;
background: red;
margin: 0 0.3%;
box-sizing: border-box;
transition: 0.7s linear;
}
.active {
color: black;
background: yellow;
}
js
function setWidth(){
if($(".item").hasClass("active")){
$(".item").width("6%");
$(".active").width("40%");
};
}
$(".item").click(function(){
$(".item").removeClass("active");
$(this).addClass("active");
setWidth();
})

Problem with PNG image on top of an image in CSS?

I am using a jQuery content rotator and I want to place a
PNG image on top of a image and on top of that text.
This is how my rotator looks like in HTML:
<div id="testimonials">
<div class="slides">
<div class = "testimonialContainer">
<div class ="leesmeer"> <img src ="http://site/afbeeldingen/test.jpg" ><div class="caption">LORUM IPSUM DOLOR SIT AMET </div></div>
</div>
<div class = "testimonialContainer">
<p class = "testimonial"> 2 </p>
<div class ="leesmeer"> <img src ="http://site/afbeeldingen/test.jpg" ></div>
</div>
</div>
</div>
Here is the CSS:
.testimonialContainer {height: 123px}
#testimonials{
width: 210px;
height: 125px;
}
.slides div{
width: 210px;
xheight: 25px;
xpadding: 5px;
.slides div.caption{
background-image: url(../images/h_contentrotator_zwart.png);
/*background-color:#000000;
filter:alpha(opacity=60);
-moz-opacity: 0.6;
opacity: 0.6;*/
color: #fff;
width: 210px;
height: 41px;
position: relative;
top: -24px;
padding: 2px 20px 2px 10px;
zbehavior: url("iepngfix.htc")
}
The problem is that the PNG image doesn't appear and also the text doesn't appear.
Can someone help me out?
You need to add a dot (.) at last selector:
.slides div.caption{
Right now it's not there, but should be.
If the problem is not solved after adding a dot
then be more specific. Change
.slides div.caption
to this:
#testimonials a div.caption
And remove Z from behaviour.
And even if it is not solved then give me a link of jQuery script homepage.
Make sure that you have the right path to the background image. If the style is in the <head> of the HTML page, then the path will be relative to the HTML page. If the style is within an external stylesheet, then the path will be relative to the file location of the stylesheet.
You also might want to get it working without the Internet Explorer 6 PNG fixes first, and then add the fixes back in after you know the rest of the code is correct.

Categories