I want to create a tiled background in which each row of the background has a random x-offset. That would be ideal, but if that's not possible with CSS (I think not), at least what's the best way to use a single image to create a body background in which this several (let's say 4) rows of this image have different x positions?
Something like:
IMAGEIMAGEIMAGEIMAGE
MAGEIMAGEIMAGEIMAGEI
AGEIMAGEIMAGEIMAGEIM
GEIMAGEIMAGEIMAGEIMA
IMAGEIMAGEIMAGEIMAGE
MAGEIMAGEIMAGEIMAGEI
AGEIMAGEIMAGEIMAGEIM
GEIMAGEIMAGEIMAGEIMA
what would be the size of your image? If is is very small, an easy solution would be to do that in photoshop/paint. The resulting image would be 4x larger, but for small images (read less than 25ko), I think it is by far the easiest way. At least I don't see any easy CSS solution to your problem.
If your picture is quite big and you know its height, you could eventually have the following approach: http://jsfiddle.net/7GPTy/
The idea is to create several divs at z-index:-1 of height == image_height and absolute position with different left values... i'd see that as a coarse but working solution
var mybody = document.getElementById('body');
var bodyHeight = mybody.offsetHeight;
var imgHeight = 49; // you could get the size by opening the file
var offsetLines = 4; // this is the number of offset you asked, but you can change that!
var nbOfLines = Math.ceil(bodyHeight/imgHeight);
for(var i=0; i<nbOfLines; i++){
var newBgDiv = document.createElement('div');
newBgDiv.className = 'backgroundImg imgOffset_'+(i%offsetLines);
newBgDiv.style.top = (i*imgHeight) + 'px';
newBgDiv.style.height = imgHeight + 'px';
newBgDiv.style.width = '100%';
mybody.appendChild(newBgDiv);
}
to go through the js code quickly, I basically get the height of the page and divide it by the height of the picture to know how many divs i have to create to generate the entire background. Once done, you simply define the number of different row offset you want (offsetLines) and you generate your divs.
In my example, the offset depends on the size of the window (try to resize horizontally your window, you'll see that the offset changes). You can of course fix it to a defined number of pixels !
If CSS3 is appropriate for your project, you can use multiple backgrounds to do this.
Make an image that is twice the height of your pattern, with the top half filled with your pattern, and the bottom half transparent.
Then use multiple backgrounds to position them accordingly like so:
.div {
background: url(path/to/image.png) 0 0 repeat,
url(path/to/image.png) 0 {height of image in pixel} repeat
}
Its not a random offset, but with enough variations to this, it would be hard to tell the difference.
If you want to add to the perceived randomness, have a look at this post.
Related
I tried to create a sort of parallax with Angular and OnScroll event, however when scrolling the text that appears is blinking. Do you know how to make the effect rendering smoother onscroll ? Maybe with CSS only ?
The script created
https://stackblitz.com/edit/angular-b5cmf7?file=src%2Fapp%2Fapp.component.html
The main function that make the effect possible is this one
#HostListener('window:scroll', ['$event'])
isScrolledIntoView(){
const offsetHeight = this.testDiv.nativeElement.children[0].offsetHeight;
const rect = this.testDiv.nativeElement.getBoundingClientRect();
if( rect.bottom <= window.innerHeight){ // when the div is visible in viewport change the height (not more than the height of the content)
let height = (window.innerHeight - rect.bottom);
if(height<offsetHeight){
this.height = height;
}else{
this.height = offsetHeight
}
}
}
As soon as I saw your blitz I recognised an issue I've run into many times. It's to do with how you calculate values on a per-frame basis. I'm not sure how best to put this in words, but it's something like this:
Don't base your calculations on values that will be modified by the result.
It's a bit abstract, but specifically in your case, the problem is with the relationship between rect.bot and this.height. With each call of your onscroll function, you modify the height of your section. But modifying the height will also modify the value of rect.bot, and on the next scroll event, you'll get a different result, so height gets modified from a different base, resulting in the oscillation you observed.
To avoid this, you want to base all your calculations only on values that are not affected by the result. In this case, I would recommend using rect.top, which doesn't care what the height of the section is.
Furthermore, I'd recommend using interpolation, because it gives you more control. The idea is you want to pick these values:
at what percentage of the window height should the reveal commence (effectively, this.height = 0)
At what percentage of the window height should the section be fully revealed (this.height = offsetHeight)
How should I interpolate between these two values? (easiest is linear)
So I've forked your blitz, and I've gone ahead and outright stolen the clamp and invlerp functions from here:
https://www.trysmudford.com/blog/linear-interpolation-functions/
You can read about these interpolation functions and their uses in that link.
you'll see I've made two variables called "startPercentage" and "endPercentage" – these are in relation to the value of rect.top as a percentage of window innerHeight. You can play around with these to get different speeds or qualities of parallax to get the effect of your liking.
Here's the fork:
https://stackblitz.com/edit/angular-lcyc4q?file=src%2Fapp%2Fapp.component.ts
And if you feel like it, look into other interpolation functions to experiment with ease-in and ease-out for different effects.
I have a HighCharts organization chart that loads data from our db so it can have a variable number of nodes. I've added
.highcharts-container { overflow: scroll !important; min-width: 100px; }
to my css so that the scrollbars appear and it seems to be growing as needed vertically. However, the nodes overlap horizontally for some reason. I've added
nodePadding: 15
to my js which seems to space them out vertically but doesn't help the horizontal issue. I feel like there should be an option or setting for this, but when I search on overlapping issues, all I get are label issues. Any ideas on how to get my nodes to space out? Thanks!
Here's a jsFiddle which has overlapping data like mine - https://jsfiddle.net/ubmzs5qf/
In case things get unconnected at some point, here's a function given to me by Sebastian here: https://www.highcharts.com/forum/viewtopic.php?f=9&t=42435&p=149331 that handles resizing for the amount of data:
events: {
load() {
let chart = this,
series = chart.series[0],
newWidth = series.options.nodeWidth * series.nodeColumns[2].length;
chart.update({
chart: {
width: newWidth
}
})
}
}
I used this to set both the height and width but it's being overwritten by something, possibly a higher angular limit on dialog size. I think I need a way to space out the icons and make everything small since I can't just make the chart bigger.
You can achieve it by decreasing nodes width eg. nodeWidth: 50.
Demo:
https://jsfiddle.net/BlackLabel/d9cmt0oy/
API reference:
https://api.highcharts.com/highcharts/series.organization.nodeWidth
EDIT
Another way is to decrease `dataLabels font size and set manually the height and offset of each larger node.
Demo:
https://jsfiddle.net/BlackLabel/8om5hc34/1/
There is one simple task I want to achieve.
I have an image in a variable width container.
The container can have a width of 300, 400, 700, or 900 pixels. This is done by the means of media-queries
The image should take up all the width of that container. So it will be also 300, 400, 700, or 900 pixels wide.
The image should have different sources for all that width values. So I can serve smaller images on mobile phones.
I thought that this could be done with the srcset attribute of the img element, maybe under help of the sizes attribute. width something like this
<img src="http://dummyimage.com/300x200/abc/000"
alt="dummy"
srcset="
http://dummyimage.com/900x200/abc/000 900w,
http://dummyimage.com/700x200/abc/000 700w,
http://dummyimage.com/400x200/abc/000 400w,
http://dummyimage.com/300x200/abc/000 300w
"
/>
But it's not working in that way, because the browser chooses the image in proportion to the width of the display port and not to that of the image itself.
Example with use of picturefill polyfill from http://scottjehl.github.io/picturefill/: http://codepen.io/HerrSerker/pen/itBJy . This does not work, because it will take the one image that is the next size.
I could of course take that into account and change my srcset to this
srcset="
http://dummyimage.com/900x200/abc/000 999999w,
http://dummyimage.com/700x200/abc/000 900w,
http://dummyimage.com/400x200/abc/000 700w,
http://dummyimage.com/300x200/abc/000 400w
"
This will work on the desktop, but fails on retina displays, because the device pixel ratio is taken into account here, but in a different way than with the media queries. And it is not useful, because the image should know about the width of the viewport and of the same width and that at compile time? No way. Image I use the image in a grid system. The image has different widthes if I'm in a 3 column grid on desktop devices and a 1 column grid on smart phones. That should not be in the responsibility of the image to calulate the ratio of width and viewport-width.
I did not have any luck with the sizes attribute as well (no example here). The reason is tha same as above. In the sizes attibute I say which amount of the viewport width should my image be wide according to media queries. This is so off. How should the image know?
So I came around with this solution. I setup a data-srcset attribute with the same syntax as the srcset attribute itself, but with a custom JavaScript programming. Example here: http://codepen.io/HerrSerker/pen/tCqJI
jQuery(function($){
var reg = /[\s\r\n]*(.*?)[\s\r\n]+([^\s\r\n]+w)[\s\r\n]*(,|$)/g;
var regw = /(.*)w/;
var sets, $set, set, myMatch, i, w, that, last;
var checkData = function() {
$('img[data-srcset]').each(function() {
that = $(this);
$set = that.data('srcset');
sets = [];
while(myMatch = reg.exec($set)) {
set = {};
set.src = myMatch[1];
set.w = (myMatch[2].match(regw))[1];
sets[set.w] = set;
}
w = that.width();
last = 0;
for (i in sets) {
last = i;
if (w <= i) {
that.attr('src', sets[i].src);
return;
}
}
that.attr('src', sets[last].src);
});
};
checkData();
$(window).on('resize', checkData);
});
This works, but it feels wrong. But maybe not, as the specifications says for responsive images to behave just in the way that it does. But I feel that it's the wrong way. 90 % of use cases for responsive images won't work with the spec.
So am I wrong? Didn't I use the srcset in the defined way? Did I understand the spec incorrectly? And do the W3C and Responsive Images Community Group think in such a way apart from reality?
Are the smaller images scaled down versions of the bigger image? Or are they cropped (art direction)? If the latter, you should use picture and source media.
The reason the browser only uses the viewport for deciding which image to download is that it's the only thing that is available when the browser wants to download an image. The CSS (probably) isn't downloaded yet. So if you use srcset+sizes, you have to repeat the breakpoints and image widths in sizes.
This question seems like a duplicate of Responsive full width image banner with fixed height using srcset
Like zcorpan said, what you are trying to do falls under the "art-direction" use-case (since the different images have different proportions), so you should use the <picture> element, rather than srcset. See the other question's answers for a syntax example.
I need to give an overlay texture to 100+ images
like this.
I have transparent .PNG texture file. if i use this as background then it will go behind the <img>. And I don't want to add another <img> or any extra span, div for texture and z-index.
Is there any other way to achieve it in CSS?
I need to use specific texture .png so i cannot use CSS gradient only.
I don't want to use main product image as background.
I'm afraid you're going to have a very hard time getting that texture overlaid on the image without some added element to put it on. If you can't affect the html output, a little javascript would do the trick.
Another option is to place the texture over the top of the other image with absolute positioning. It's hard to know if that's a viable option without more context, however. Here's an example: http://jsfiddle.net/cPSFQ/1/.
Glad your post is tagged with CSS3
http://jsfiddle.net/WQTeE/2/
You have to create a reverse mask of the overlay. I tested this in FF9 and Chrome 16
img.stockphoto{
-webkit-mask-box-image: url(http://koivi.com/php-gd-image-watermark/watermarks/Sample-trans.png);
-o-mask-image: url(http://koivi.com/php-gd-image-watermark/watermarks/Sample-trans.png);
-moz-mask-image: url(http://koivi.com/php-gd-image-watermark/watermarks/Sample-trans.png);
mask-image: url(http://koivi.com/php-gd-image-watermark/watermarks/Sample-trans.png);
}
You can try this.
http://jsfiddle.net/Bs7nv/
In this all I am doing is displaying an image and a div in which we can use the texture image as background and absolute positioning to display over the actual image.
There is no pure css solution to your question that's cross browser compatible. I realize that this answer doesn't meet your original criteria, but I figured I'd supply it anyways so that you could have it as an option.
Using pseudo elements (:before) would be a logical choice for CSS3, but alas, they don't work on img tags.
You'll have to do something, rather change the mark-up or add some javascript. Assuming you can't edit the mark-up (sometimes you can't control your source data), but can control the javascript, you could do it with pure javascript like this:
var transparentImage = "http://rd.cas.de/tim/native/image.png";
var imageList = document.getElementsByTagName("img");
var arrImages = [];
for (var i = 0; i < imageList.length; i++ ) {
// store the images as is first, otherwise the list is living and
// you loop forever...
arrImages.push(imageList[i]);
}
for (i = 0; i < arrImages.length; i++ ) {
// first wrap all the images in a relative positioned div.
var wrapper = document.createElement('div');
var newImg = document.createElement("img");
newImg.setAttribute("src", transparentImage);
newImg.style.position = "absolute";
wrapper.appendChild(newImg);
wrapper.appendChild(arrImages[i].cloneNode(true));
arrImages[i].parentNode.replaceChild(wrapper, arrImages[i]);
}
Here's a jsfiddle that does what you want (but with javascript).
Here's my problem, I need to scale and clip images into square sized tiles to put into a tile list. Here's how I want it to work:
I want all my tiles to be, say, 300px x 300px.
For each image, I want to scale the shorter side (either width or height) to fit in the tile using the "letterbox" scaleMode (so that it maintains aspect ratio).
Then I want to position the image in the center and clip away anything left over from either both sides or the top and bottom.
Here's an example to help clarify:
I have an image with width=600px and height=1200px. First I want to scale the image to width=300px and height=600px (notice that aspect ratio is maintained), then center the image vertically and clip the image to 300 x 300.
Is this possible? This is actually a pretty standard way of displaying square thumbnails in many photo-based web sites, but I can't find a way to make it work in flex.
Any help would be appreciated, thanks!
UPDATE JUNE 2012:
Just in case anyone finds this thread now, this issue has been resolved in the latest version of the Flex SDK. On the spark image object there is a new scaleMode of "zoom" which does exactly what I've asked for here.
Take your big image and draw it on BitmapData with scale and reposition:
const zoom:Number = Math.max(THUMB_WIDTH/image.width, THUMB_HEIGHT/image.height);
const x:int = (THUMB_WIDTH - image.width*zoom)/2;
const y:int = (THUMB_HEIGHT - image.height*zoom)/2;
var matrix:Matrix = new Matrix;
matrix.scale(zoom, zoom);
matrix.translate(x, y);
var _thumbBitmap:BitmapData = new BitmapData(THUMB_WIDTH, THUMB_HEIGHT, false, 0xFFFFFF);
_thumbBitmap.draw(image, matrix, null, null, null, true);
Then assign resulting BitmapData to the source of the BitmapImage.
More: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html#draw%28%29
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/primitives/BitmapImage.html#source