I'm using SASS/SCSS and want to create a #function/#mixin which will figure the max possible font-size for a container, given a dynamic width.
For example:
<body style="font-size: 10px;">
<div style="width: 960px;"> <!--This width is dynamic-->
<span style="font-size: 12.3em">Patrick Rocks</span>
</div>
</body>
The unknown variable in this equation is the font-size on the <span> tag. I set it to 12.3em which would be 123px (relative to the font-size of the <body> tag), but that could change depending on letter-spacing font-family or other aspects. Perhaps because of the complexity of this it would be best served to calculate this with JavaScript, or PHP.
You can't do this on the server side, as the user's font may have any dimensions. You'll have to do it in javascript, in the browser.
I've worked it through and found a solution which fits my needs. The solution only works if the following is known.
The exact text being used
The font being used
The default width based on the parent font-size
DEMO:
http://wecodesign.com/demos/stackoverflow-7420897.htm
SCSS:
$logoDefaultWidth: 76; /*Pixels*/
#function getFontSize($newLogoWidth) {
$fontSize: $newLogoWidth/$logoDefaultWidth;
#return #{$fontSize}em;
}
#function pxToEm($px) {
#return #{$px/10}em;
}
body {
font-size: 10px;
}
.logo {
width: pxToEm($logoDefaultWidth);
}
.logo.s960 {
font-size: getFontSize(960);
}
.logo.s480 {
font-size: getFontSize(480);
}
HTML:
<div class="logo s960">Patrick Rocks</div>
<div class="logo s480">Patrick Rocks</div>
TODO:
This solution has a known issue with WebKit (Chrome/Safari) browers. WebKit browsers render #font-face font's much thicker than they should, thus making the $logoDefaultWidth incorrect. I'm working on trying to find out how to stop WebKit from making the font so thick, or on a separate calculation for WebKit.
Related
I'd like to set a random background-image into a <div>Container</div>
To keep it simple I installed a plugin using [shortcode] to display random images. This works fine.
How to get the shortcode [wp-image-refresh] working together with background-image:url(...)
I tried it even as inline-style with no result.
This is what I have:
HTML
<div class="header_random-image">
<div id="hero"></div>
</div>
CSS
#hero {
background-image: url('<?php echo do_shortcode("[wp-image-refresh]"); ?>');
background-size: cover;
background-position: 50% 30%;
height:70vh;
width: 100%;
margin-top: -65px;
}
Another try with no result: Inline-style
<div class="header_random-image">
<div style="background-image: url('<?php echo do_shortcode("[wp-image-refresh]"); ?>')"></div>
</div>
Could anybody be so kind to help? Or does anybody has a simple solution to place div-random-background-images?
Best from Berlin
In most cases your CSS code will be served in a static file, thus the php code won't execute.
As the inline example doesn't work either, I guess the short code does not return an image url but a full image tag instead. The plugin's description
confirms this assumption. WP-IMAGE-REFRESH
You could try this:
PHP
<div class="header_random-image">
<?php echo do_shortcode("[wp-image-refresh class='hero_class']"); ?>
</div>
CSS
.header_random-image {
overflow: hidden;
}
.hero_class {
height: 100%;
width: auto;
margin-top: 0;
}
This should display the image. You'd still have to center it if you want (use flex-box) and check for problems caused on different screen sizes depending on the side ratio of your uploaded images and solve them with some Javascript.
Alternative
Use ACF Pro and add a gallery field to your posts/pages or an option page if you want the same images on all views.
PHP
<?php
$images = get_field('name-of-your-gallery-field');
shuffle($images);
$imageUrl = images[0]['url'];
<div class="header_random-image">
<div style="background-image: url('<?= $imageUrl ?>"); ?>')"></div>
</div>
Let's say we need to display 2 different images for mobile and desktop. We would usually do something like this:
HTML
<div class="container"></div>
CSS
.container {
background-image: url('image-for-mobile.jpg');
}
#media (min-width: 1024px) {
.container {
background-image: url('image-for-desktop.jpg');
}
}
But what happens when we are getting those images from the server? Let's say from Wordpress or any other source?
One way to do it, would be:
HTML
<div class="container for-mobile" style="background-image: url(<?php echo $img_for_mobile; ?>);"></div>
<div class="container for-desktop" style="background-image: url(<?php echo $img_for_desktop; ?>);"></div>
CSS
.for-mobile {
display: block;
}
.for-desktop {
display: none;
}
#media (min-width: 1024px) {
.for-mobile {
display: none;
}
.for-desktop {
display: block;
}
}
For obvious reasons, even though this "works" this is not right because we are repeating the markup. What if we have a ton of content inside '.container'? We would have to repeat all that, only to have a different background image.
Another option would probably be passing the variables as data attributes and then with jQuery getting those variables and assigning the right background image in relation to the screen size. Something like this:
HTML
<div class="container" data-mobile="<?php echo $img_for_mobile; ?>" data-desktop="<?php echo $img_for_desktop; ?>"></div>
jQuery
// This is pseudo code, not tested
var imgForMobile = $('.container').data('mobile');
var imgForDesktop = $('.container').data('desktop');
$(window).on('resize', function() {
if ($(window).width() < 1024) {
$('.container').css('background-image', 'url(' + imgForMobile + ')');
}
else {
$('.container').css('background-image', 'url(' + imgForDesktop + ')');
}
});
How could we attack this situation in a more elegant and proper way? Any thoughts would be much appreciated. Thanks in advance!
The correct way:
This is what image srcset is for!
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
If I had to guess though, I think you would benefit from using this and object-fit together. Do you want the background image to be sized to cover?
If so, this is way the super responsive and efficient way to do this:
.container {
position: relative;
}
.container img {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
object-fit: cover;
}
<div class="container">
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
</div>
The older server side way:
If you really wanted to do it in PHP like you have in the example, this is the pattern we use for things like this in WordPress.
$image = 'desktop.jpg';
switch (true) {
case wp_is_mobile() :
$image = 'mobile.jpg';
break;
}
<div class="container" style="background-image: url(<?php echo $image; ?>);"></div>
You can still use the CSS approach, by passing in a full URL or CDN.
If the rule inside of a media query that is false, that image won't be loaded by the browser.
.container {
background-image: url('https://www.example.com/image-for-mobile.jpg');
}
#media (min-width: 1024px) {
.container {
background-image: url('https://www.example.com/image-for-desktop.jpg');
}
}
There are alternatives which place this logic in either your HTML, JS, or even server code. HTML's answer is using a srcset attribute with an image, or using a <picture> element instead which was introduced in HTML5. srcset on an image is typically used to handle differences in pixel density, while the <picture> element is used to serve varying images using media queries. The first <source> whose media query matches the document is served, and you can include a general fallback, which allows backward compatibility for older browsers, however this approach loads at least 2 images - as the fallback will always be loaded.
<picture>
<source srcset="big.jpg 1x, big-2x.jpg 2x, big-3x.jpg 3x" media="(min-width: 40em)" />
<source srcset="med.jpg 1x, med-2x.jpg 2x, med-3x.jpg 3x" />
<img src="fallback.jpg" alt="fancy pants" />
<!-- fallback.jpg is *always* downloaded -->
</picture>
The way I did it in my site was I used JQuery to check if its a mobile browser (quick google will find the if statement used, its rather long)
Edit:
Here: if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
$('body').addClass('mobile');
}
I made it append the body tags with class='mobile'
and then in my CSS I have two sets:
body {
background:black;
}
.mobile body {
background: blue;
}
I'm trying to display images using CSS so that I can switch which image is being displayed depending on what stylesheet is selected. It works fine sometimes, others not. Can you help me figure out why?
I first use php to echo out the HTML based on the page id:
if($host == 'comparison.php?page=1.1.9')
{
echo "<div class='image8'></div>";
}
if($host == 'comparison.php?page=1.1.10')
{
echo "<div class='image9'></div>";
}
In the CSS, I identify the class, and tell it to display the image:
div.image8 {
content:url(homilies/1.1.9.jpg);
width: 100%;
}
div.image9 {
content:url(homilies/1.1.10.jpg);
width: 100%;
}
1.1.10 works perfectly, and the image changes when I select another stylesheet. 1.1.9 does not work at all, and when I inspect the element, the 'div.image8' doesn't even show up. What could be going on here? It works in other places too, I can't figure out the pattern.
Ok D.C, I'm in a good mood and like I mentioned in a comment above, I created a quick, down and dirty, one page code to test your situation. Everything worked great for me, but I did learn a few things too. I have no idea how 1.1.10 worked perfectly for you but not 1.1.9 because from what I can tell neither should work. Tested in Firefox v53.0.2.
Using content:url('some_image'); never showed the image for me.
Had to use background-image: url('some_image'); for an image to appear.
The DIV needed a non-breaking space ( ) between the DIV tags for the DIV to show the image. In other words, you can't have a background image if there is no content in the DIV. So maybe you just need to add a non-breaking space between your DIV tags to make it work?
That's about it. Now for a working example. You can and should modify it to fit your needs. For example link the style sheet instead of internal like I did. I just wanted to make a quick one page of code to test if everything will work.
<?php
//Use a PHP ternary operator to check if the GET variable is set in the URL.
$page=isset($_GET['page'])?$_GET['page']:'';
switch ($page) {
case '1.1.9':
$img_class='image8';
break;
case '1.1.10':
$img_class='image9';
break;
case '1.1.11':
$img_class='image10';
break;
default:
$img_class='image0';
break;
}
?>
<!DOCTYPE HTML>
<html>
<head>
<title>Image By Get Var</title>
<style>
/*Everything between the STYLE tags would actually be in your style sheet instead of internal to your page.*/
html, body {
height: 100%;
background: #ccc;
padding: 10px;
}
#img_container {
margin-top: 20px;
background-repeat: no-repeat;
background-size: contain;
height: 50%;
width: 50%;
}
/* You can use the static images below to test this code, but should replace with your images using a relative path.*/
/* Used tinypic.com for demo images since it allows free hotlinking. */
div.image0 {
background-image: url('http://i50.tinypic.com/j9blw9.jpg');
}
div.image8 {
background-image: url('http://i42.tinypic.com/5n52ex.jpg');
}
div.image9 {
background-image: url('http://i60.tinypic.com/316ozv5.jpg');
}
div.image10 {
background-image: url('http://i43.tinypic.com/2eg5j7s.jpg');
}
</style>
</head>
<body>
<p>The form only exists so that a GET variable can be sent to the page to test PHP setting CSS based on the GET variable.</p>
<form method="get">
<input type="radio" name="page" value="1.1.9"> 1.1.9<br>
<input type="radio" name="page" value="1.1.10"> 1.1.10<br>
<input type="radio" name="page" value="1.1.11"> 1.1.11<br>
<input type="submit" value="Submit">
</form>
<form>
<input type="submit" value="Reset To Default">
</form>
<?php
/* The div container has a non-breaking space so that the div will exist to have a background */
echo '
<div id="img_container" class="'.$img_class.'"> </div>
';
?>
</body>
</html>
I hope that helps. If 1.1.9 still does not work when you replace the image in my example with the relative path to your image, then you should make sure that the image is located in the path that you have specified.
Good luck!
Found the solution, for anyone interested: after using a CSS validator, I found that there were invisible characters mucking things up. Lesson learned.
I'm trying to give the first div a top margin only if the class fixed-header exists, I've tried doing this with pure css but there were to many variables and I was losing track so I'm thinking use jquery.
Here's some simple html
<div id="page-container">
<div id="header" class="fixed-header">header</div>
<div>Test 2</div>
<div>Test 3</div>
<div>Test 4</div>
<div>Test 5</div>
</div>
Basically, if .fixed-header does exists give the first div, in this case it's 'test2' a top margin which matches the header, if there is no 'div2' then give 'div3' a top margin and so on.
Now for the tricky part, the top margin must be determined from a php script, here's how I get the header height below.
<?php echo $header_options['header_height'] ?>
How can I do this in jquery?
Here's a basic fiddle to start me off
If i understood you correctly, you can do that in CSS like that:
.page-container div.fixed-header:nth-child(1) + div,
.page-container div:not(.fixed-header):nth-child(1){
margin-top:20px;
// or
margin-top: <?php echo $header_options['header_height'] ?>px;
background:red;
}
this will give the first div after .fixed-header or the first one in .page-container (if no fixed-header exists) a margin.
Demo
If you want the margin be exactly the same as the height of the header without php, then yes, you'll have to resort to javascript/jquery. Something like this
$('#page-container div.fixed-header:nth-child(1)').each(function(){
$(this).next().css({'margin-top':$(this).height()});
});
Use length to find the div exits or not:
if($('.fixed-header').length > 0){
//do your stuff here
}
And I think it should work just with css:
#page-container .fix-header{
margin: 5px;
}
You can do this in CSS alone you know....you dont need to resort to Javascript or jQuery.
#page-container div:nth-child(1)[class='fixed-header']{
background:red;
}
Demo of the above, variation 1, variation 2
Use CSS in the head of the page:
#page-container #header.fixed-header + div {
/* the following should be parsed by php, but
I don't know whether this generates a full CSS
rule, or just the relevant length. Adjust as appropriate */
<?php echo $header_options['header_height'] ?>
}
There's no need for jQuery in here...
You want to div that follows .fixed-header to have a margin? Use the adjacent selector "+"
<style>
#header.fixed-header {height: <?php echo $header_options['header_height'] ?>px}
#header.fixed-header + div {margin-top: <?php echo $header_options['header_height'] ?>px}
</style>
Btw, you could just set a margin-bottom on #header.fixed-header... ;-)
Well, if each margin is the same, then give a data-attribute to the container. If each margin has different height, the most intuitive option is to put a data attribute to each item.
If each margin is the same, here is you code
$(".fixed-header").each(function(item) {
$($(item).next()).css('margin-top', $(item).parent().data('margin-height'));
});
Your markup should look like this:
<div id="page-container" data-margin-height="50px">
<div id="header" class="fixed-header">header</div>
<div>Test 2</div>
<div>Test 3</div>
<div>Test 4</div>
<div>Test 5</div>
</div>
This is equivalent to the following CSS, if every page-container has the same value as well.
.page-container .fixed-header + div {
margin-top: 50px;
}
You can generate this CSS file with your PHP as well. To make life easier, you can even embed this to you HTML template. If the margin-height does not reflect any information, then possibly generating your CSS is the best option, because then, you don't need to put useless information outside a <style> or <script> tag.
<style>
.page-container .fixed-header + div {
margin-top: <?php echo $header_options['header_height'] ?>;
}
</style>
Another option is to use CSS3 attr, which is not yet supported completely in all browsers.
https://developer.mozilla.org/en-US/docs/Web/CSS/attr
.page-container .fixed-header + div {
margin-top: attr(data-margin-height);
}
This allows you to get rid of your script, but unfortunately, you will have to set data-margin-height for each .fixed-header.
I used .page-container classes in these examples, because this solution can be used if you have multiple different containers on the same page. If you only need one, you can just replace each .page-container to #page-container, and the code will work. Fiddle:
http://jsfiddle.net/k5V2a/
I'm creating an e-commerce site and I'm having trouble vertically centering all my thumbnails. The problem is all my images are different sizes and getting each one to vertical align across all browsers is turning out to be a pain. I've looked into the different CSS options, display-table, line-height, and others. They worked in modern browsers, but not well in IE (of course). My thought is the large big time sites are resizing the image (which I can do with no problem) and then overlaying the image on top of a background the exact size they need. Does anyone know if this is how it's done? IF so can you direct me to some documentation of how to do this in PHP?
Or if someone thinks I can do this without all the extra work of overlaying images please let me know. In-case you want to see what I'm working with here ya go:
HTML
<a href="#">
<div id="product">
<div id="product-image">
<img src="" border="0" />
</div>
<div id="product-name"></div>
<div id="product-price"></div>
</div>
</a>
OPTION 1 : JQUERY (this seemed to be my best hope, but couldn't get it to work right)
var h = $('#product-image').height();
$.map($('#product-image img'), function(e)
{
var top =( h- $(e).height())/2;
$(e).css("margin-top",top);
});
OPTION 2 : CSS
#product
{
float:left;
margin:5px;
width:200px;
height:200px;
border:1px solid #999;
}
#product-image
{
margin:2px auto;
width:194px;
height:145px;
text-align:center;
}
#product-image img
{
max-height: 100%;
max-width: 100%;
vertical-align:middle;
}
EDIT
I found the working code, thanks Explosion Pills. For anyone trying to get this work I would suggest using this jQuery method and Fiddle link http://jsfiddle.net/9VfUS/1/:
WORKING JQUERY
var h = $('div#product-image').height();
$('div#product-image img').each(function ()
{
var top = (h - $(this).height()) / 2;
$(this).css("margin-top",top);
});
If you can use JavaScript, I would do it that way as it's surefire to get things to work the way you want. You are using .map for the wrong purpose. You want .each:
$('#product-image img').each(function () {
var top = (h - $(this).height()) / 2;
$(this).css("margin-top",top);
});
I assume that h was already calculated correctly as the tallest image or the height of the container or what have you. If it's not, then you have to do that.
Try this, if you know in advance the sizes of your images...
HTML:
<a href="#">
<div class="product">
<div class="product-image" data-image-loc="path_to_your_image"> </div>
<div class="product-name"></div>
<div class="product-price"></div>
</div>
</a>
CSS:
div.product-image {
background-position:center center;
background-repeat:no-repeat;
background-color: transparent;
background-attachment: scroll;
}
div.product-image-width-x-height {
width:{width}px;
height:{height}px;
}
JS:
$(document).ready(function() {
$('div.product-image').each(function() {
$(this).css({backgroundImage:url($(this).attr('data-image-loc'))});
});
});
If you don't know your sizes, then a resize script that serves all your images to a new size would fix that, and you would simply move the width/height css properties to the div#product-image CSS declaration.