Modify an internal href link for only narrower screens - html

I have an 'overview' html page with lots of product images - each image links to a page that may have 3 or 4 products, eg, src="gadgets-1.html"
On desktop, on the destination page the user can see most products or can easily scroll down if needed.
But on narrow screen where the css MQs convert all columns to 100% width, the last items are not necessarily in view and the user must intuit that it's necessary to swipe down the page, so I want the linking image to link directly to the relevant item on the destination page.
I've established anchor links which work well, eg, src="gadgets-1.html#red-thing" but I don't want the '#red-thing' to be active on wider screens.
To resume, I want the link to be gadgets-1.html on wider screen and
gadgets-1.html#red-thing on narrow screen.
I don't see how this can (or should) be done with css. Should js or php be used? If so, how?

There are a couple of solutions I can think off of the top of my head. I don't usually like using javascript to modify the DOM based on screenwidth but it is an acceptable solution if you are so inclined.
OR you can do something simple like this:
<div class="links">
<a class="mobileLink" href="gadgets-1.html#red-thing">gadgets-1</a>
<a class="desktopLink" href="gadgets-1.html">gadgets-1</a>
</div>
with some css to hide the right link based on screen width
.mobileLink{
display: none;
}
#media screen and (max-width: 992px) {
.mobileLink{
display: inline-block;
}
.desktopLink{
display: none;
}
}

A flexible solution would be to use Javascript with a specific data- attribute for storing the different anchor names.
HTML:
<a class="targetLink" href="/link1" data-anchor="anchor-name1">Target link</a>
<a class="targetLink" href="/link2" data-anchor="anchor-name2">Target link</a>
To execute the code cross-browser on DOM ready and window resize, jQuery would be useful.
Check CodePen here
$(document).ready(function() {
var $target = $(".targetLink");
var $window = $(window);
var breakpoint = 640;
var linkSmall = false;
function checkWidth() {
if ($window.width() <= breakpoint) {
// appends anchors to links
if(!linkSmall){
$target.each(function(index) {
var href2 = $(this).attr("href") + "#" + $(this).attr("data-anchor");
$(this).attr("href", href2 );
});
linkSmall = true;
}
}else{
// removes anchors to links
if(linkSmall){
$target.each(function(index) {
var href1 = $(this).attr("href");
var a = href1.indexOf('#');
var href2 = href1.substring(0, a != -1 ? a : href1.length);
$(this).attr("href", href2 );
});
linkSmall = false;
}
}
}
checkWidth(); // on document ready
$(window).resize(checkWidth); // on window resize
});

As you don't want to repeat anchor elements(as per the other threads), you won't be able to do it with css so you'll have to use js.
if(window.innerwidth < 911){
document.getElementsByClassName("class")[0].setAttribute("href", "url_for_small_screen_devices);
}else{
document.getElementsByClassName("class")[0].setAttribute("href", "url_for_normal_desktop_and_bigger_devices");
}
you can use a loop to repeat the same process for all anchors with using proper selectors.

Related

How to Load Different Home Page according to screen size

I want to load different home page according screen size. Can anyone help about it ?
For Example,
for screen-size < 960 px I want to display default landing page as index1.html
and
for screen-size > 960 px I want to display default landing page as index2.html
Thanks in advance.
I know this was asked and answered a while ago, but I think the solution I'm adding is better than the accepted answer as it involves no reloading and works on resizing. Define two CSS classes, .HideOnMobile and .ShowOnMobile and use them in two top level DIV elements.
Then use media queries to set the display value of those two classes to non or initial, to display or hide each DIV according to the screen width.
#media (max-width: 575.98px) {
.HideOnMobile {
display: none;
}
.ShowOnMobile {
display: initial;
}
}
#media (min-width: 576px) {
.HideOnMobile {
display: initial;
}
.ShowOnMobile {
display: none;
}
}
<div class="ShowOnMobile">
MOBILE content
</div>
<div class="HideOnMobile">
DESKTOP content
</div>
You've tagged this question responsive-design, but you are asking about how to do "adaptive design." Responsive design would be having a single HTML page that adjusts to the medium it is being viewed in, for example by using media queries. I won't get into a debate about which is better, but I add this in case you're interested in responsive design so that you have some ideas to google.
A way to do what you are asking is to have a bit of JavaScript on your page that checks the width of the window and redirects if necessary:
// In index2.html
if (window.innerWidth < 960) {
window.location = "index1.html";
}
// In index1.html
if (window.innerWidth >= 960) {
window.location = "index2.html";
}
I tried the above solution. It worked but the page was reloading continuously. By this approach solved the reload problem and I've added a function that can help reload the page automatically when viewport size change.
// refreshing page automatically when viewport size change
window.onresize = function(event) {
document.location.reload(true);
}
var href = window.location.href.split("/")
var html_location = href[href.length-1]
if (window.innerWidth >= 960 && html_location !== "index.html") {
window.location = "index.html";
}
if (window.innerWidth < 960 && html_location !== "index2.html") {
window.location = "index2.html";
}

Remove Certain CSS Style from Html Page

I have a Html page which has anchor tag, I Need to remove certain style applied already in html page for anchor tag while the html page is opened throw Iframe.
HTML Content as below:
<html>
<body>
<div>some content<a href="http://www.website.com" name="test1"/> some content </div>
</body>
</html>
I tried as below:
a[name^="test1"]:before{
content:"[prefix text]";
display:inline;
color:red;
}
a[name^="test1"]:after{
content:"suffix text";
display:inline;
color:green;
}
iframe a[name^="test1"]:before{
display:none;
}
iframe a[name^="test1"]:after{
display:none;
}
But inside "iframe" also these styles has been applying.
You have to first detect if your page is rendered inside an iframe and in that case apply an alternative CSS. It' can't be done with vanilla CSS then it has to be done with some JavaScript:
<script type="text/javascript">
function getTopWindow() {
try {
return window.top;
} catch {
// If we can't access window.top then browser is restricting
// us because of same origin policy.
return true;
}
}
function isRendererdInFrame() {
// If top window is null we may safely assume we're in iframe
return window.self !== getTopWindow();
}
function loadCss(location) {
if(document.createStyleSheet) {
document.createStyleSheet('http://server/stylesheet.css');
} else {
var styles = "#import url('" + location + "');";
var newSS=document.createElement('link');
newSS.rel='stylesheet';
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
}
}
</script>
Code to load CSS from JavaScript is from How to load up CSS files using Javascript?.
With all that code you may simply write (even just after that inside <script> block):
var cssToLoad = isRendererdInFrame() ? "iframe.css" : "not-iframe.css";
loadCss("http://server/" + cssToLoad);
Of course same technique can be applied to patch CSS with iframe specific styles:
if (isRenderedInFrame())
loadCss("http://server/iframe-patch.css");
i dont know how to detect if page is opened in iframe or not, but there is one possible(not very nice) workaround, you can set iframe to width which is not commonly used by devices (example 463px) and then set media query for this resolution which apply when content is shown in this iframe. This is really nasty way since its not 100% and i would not recommending that.

Go to last div added inside div [duplicate]

I am creating a chat using Ajax requests and I'm trying to get messages div to scroll to the bottom without much luck.
I am wrapping everything in this div:
#scroll {
height:400px;
overflow:scroll;
}
Is there a way to keep it scrolled to the bottom by default using JS?
Is there a way to keep it scrolled to the bottom after an ajax request?
Here's what I use on my site:
var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
This is much easier if you're using jQuery scrollTop:
$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
Try the code below:
const scrollToBottom = (id) => {
const element = document.getElementById(id);
element.scrollTop = element.scrollHeight;
}
You can also use Jquery to make the scroll smooth:
const scrollSmoothlyToBottom = (id) => {
const element = $(`#${id}`);
element.animate({
scrollTop: element.prop("scrollHeight")
}, 500);
}
Here is the demo
Here's how it works:
Ref: scrollTop, scrollHeight, clientHeight
using jQuery animate:
$('#DebugContainer').stop().animate({
scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
Newer method that works on all current browsers:
this.scrollIntoView(false);
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));
Works from jQuery 1.6
https://api.jquery.com/scrollTop/
http://api.jquery.com/prop/
alternative solution
function scrollToBottom(element) {
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}
smooth scroll with Javascript:
document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });
If you don't want to rely on scrollHeight, the following code helps:
$('#scroll').scrollTop(1000000);
Java Script:
document.getElementById('messages').scrollIntoView(false);
Scrolls to the last line of the content present.
My Scenario: I had an list of string, in which I had to append a string given by a user and scroll to the end of the list automatically. I had fixed height of the display of the list, after which it should overflow.
I tried #Jeremy Ruten's answer, it worked, but it was scrolling to the (n-1)th element. If anybody is facing this type of issue, you can use setTimeOut() method workaround. You need to modify the code to below:
setTimeout(() => {
var objDiv = document.getElementById('div_id');
objDiv.scrollTop = objDiv.scrollHeight
}, 0)
Here is the StcakBlitz link I have created which shows the problem and its solution : https://stackblitz.com/edit/angular-ivy-x9esw8
If your project targets modern browsers, you can now use CSS Scroll Snap to control the scrolling behavior, such as keeping any dynamically generated element at the bottom.
.wrapper > div {
background-color: white;
border-radius: 5px;
padding: 5px 10px;
text-align: center;
font-family: system-ui, sans-serif;
}
.wrapper {
display: flex;
padding: 5px;
background-color: #ccc;
border-radius: 5px;
flex-direction: column;
gap: 5px;
margin: 10px;
max-height: 150px;
/* Control snap from here */
overflow-y: auto;
overscroll-behavior-y: contain;
scroll-snap-type: y mandatory;
}
.wrapper > div:last-child {
scroll-snap-align: start;
}
<div class="wrapper">
<div>01</div>
<div>02</div>
<div>03</div>
<div>04</div>
<div>05</div>
<div>06</div>
<div>07</div>
<div>08</div>
<div>09</div>
<div>10</div>
</div>
You can use the HTML DOM scrollIntoView Method like this:
var element = document.getElementById("scroll");
element.scrollIntoView();
Javascript or jquery:
var scroll = document.getElementById('messages');
scroll.scrollTop = scroll.scrollHeight;
scroll.animate({scrollTop: scroll.scrollHeight});
Css:
.messages
{
height: 100%;
overflow: auto;
}
Using jQuery, scrollTop is used to set the vertical position of scollbar for any given element. there is also a nice jquery scrollTo plugin used to scroll with animation and different options (demos)
var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;
if you want to use jQuery's animate method to add animation while scrolling down, check the following snippet:
var myDiv = $("#div_id").get(0);
myDiv.animate({
scrollTop: myDiv.scrollHeight
}, 500);
I have encountered the same problem, but with an additional constraint: I had no control over the code that appended new elements to the scroll container. None of the examples I found here allowed me to do just that. Here is the solution I ended up with .
It uses Mutation Observers (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) which makes it usable only on modern browsers (though polyfills exist)
So basically the code does just that :
var scrollContainer = document.getElementById("myId");
// Define the Mutation Observer
var observer = new MutationObserver(function(mutations) {
// Compute sum of the heights of added Nodes
var newNodesHeight = mutations.reduce(function(sum, mutation) {
return sum + [].slice.call(mutation.addedNodes)
.map(function (node) { return node.scrollHeight || 0; })
.reduce(function(sum, height) {return sum + height});
}, 0);
// Scroll to bottom if it was already scrolled to bottom
if (scrollContainer.clientHeight + scrollContainer.scrollTop + newNodesHeight + 10 >= scrollContainer.scrollHeight) {
scrollContainer.scrollTop = scrollContainer.scrollHeight;
}
});
// Observe the DOM Element
observer.observe(scrollContainer, {childList: true});
I made a fiddle to demonstrate the concept :
https://jsfiddle.net/j17r4bnk/
Found this really helpful, thank you.
For the Angular 1.X folks out there:
angular.module('myApp').controller('myController', ['$scope', '$document',
function($scope, $document) {
var overflowScrollElement = $document[0].getElementById('your_overflow_scroll_div');
overflowScrollElement[0].scrollTop = overflowScrollElement[0].scrollHeight;
}
]);
Just because the wrapping in jQuery elements versus HTML DOM elements gets a little confusing with angular.
Also for a chat application, I found making this assignment after your chats were loaded to be useful, you also might need to slap on short timeout as well.
Like you, I'm building a chat app and want the most recent message to scroll into view. This ultimately worked well for me:
//get the div that contains all the messages
let div = document.getElementById('message-container');
//make the last element (a message) to scroll into view, smoothly!
div.lastElementChild.scrollIntoView({ behavior: 'smooth' });
small addendum: scrolls only, if last line is already visible. if scrolled a tiny bit, leaves the content where it is (attention: not tested with different font sizes. this may need some adjustments inside ">= comparison"):
var objDiv = document.getElementById(id);
var doScroll=objDiv.scrollTop>=(objDiv.scrollHeight-objDiv.clientHeight);
// add new content to div
$('#' + id ).append("new line at end<br>"); // this is jquery!
// doScroll is true, if we the bottom line is already visible
if( doScroll) objDiv.scrollTop = objDiv.scrollHeight;
Just as a bonus snippet. I'm using angular and was trying to scroll a message thread to the bottom when a user selected different conversations with users. In order to make sure that the scroll works after the new data had been loaded into the div with the ng-repeat for messages, just wrap the scroll snippet in a timeout.
$timeout(function(){
var messageThread = document.getElementById('message-thread-div-id');
messageThread.scrollTop = messageThread.scrollHeight;
},0)
That will make sure that the scroll event is fired after the data has been inserted into the DOM.
This will let you scroll all the way down regards the document height
$('html, body').animate({scrollTop:$(document).height()}, 1000);
You can also, using jQuery, attach an animation to html,body of the document via:
$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);
which will result in a smooth scroll to the top of the div with id "div-id".
Scroll to the last element inside the div:
myDiv.scrollTop = myDiv.lastChild.offsetTop
You can use the Element.scrollTo() method.
It can be animated using the built-in browser/OS animation, so it's super smooth.
function scrollToBottom() {
const scrollContainer = document.getElementById('container');
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
left: 0,
behavior: 'smooth'
});
}
// initialize dummy content
const scrollContainer = document.getElementById('container');
const numCards = 100;
let contentInnerHtml = '';
for (let i=0; i<numCards; i++) {
contentInnerHtml += `<div class="card mb-2"><div class="card-body">Card ${i + 1}</div></div>`;
}
scrollContainer.innerHTML = contentInnerHtml;
.overflow-y-scroll {
overflow-y: scroll;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="d-flex flex-column vh-100">
<div id="container" class="overflow-y-scroll flex-grow-1"></div>
<div>
<button class="btn btn-primary" onclick="scrollToBottom()">Scroll to bottom</button>
</div>
</div>
Css only:
.scroll-container {
overflow-anchor: none;
}
Makes it so the scroll bar doesn't stay anchored to the top when a child element is added. For example, when new message is added at the bottom of chat, scroll chat to new message.
Why not use simple CSS to do this?
The trick is to use display: flex; and flex-direction: column-reverse;
Here is a working example. https://codepen.io/jimbol/pen/YVJzBg
A very simple method to this is to set the scroll to to the height of the div.
var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
On my Angular 6 application I just did this:
postMessage() {
// post functions here
let history = document.getElementById('history')
let interval
interval = setInterval(function() {
history.scrollTop = history.scrollHeight
clearInterval(interval)
}, 1)
}
The clearInterval(interval) function will stop the timer to allow manual scroll top / bottom.
I know this is an old question, but none of these solutions worked out for me. I ended up using offset().top to get the desired results. Here's what I used to gently scroll the screen down to the last message in my chat application:
$("#html, body").stop().animate({
scrollTop: $("#last-message").offset().top
}, 2000);
I hope this helps someone else.
I use the difference between the Y coordinate of the first item div and the Y coordinate of the selected item div. Here is the JavaScript/JQuery code and the html:
function scrollTo(event){
// In my proof of concept, I had a few <button>s with value
// attributes containing strings with id selector expressions
// like "#item1".
let selectItem = $($(event.target).attr('value'));
let selectedDivTop = selectItem.offset().top;
let scrollingDiv = selectItem.parent();
let firstItem = scrollingDiv.children('div').first();
let firstItemTop = firstItem.offset().top;
let newScrollValue = selectedDivTop - firstItemTop;
scrollingDiv.scrollTop(newScrollValue);
}
<div id="scrolling" style="height: 2rem; overflow-y: scroll">
<div id="item1">One</div>
<div id="item2">Two</div>
<div id="item3">Three</div>
<div id="item4">Four</div>
<div id="item5">Five</div>
</div>

Is it possible to make a hidden section of a web page that is only visible when using an anchor link?

I would like to add a section to an existing webpage, but only make it visible if the user types the URL with a particular anchor link. Is this possible? Or is it possible to redirect to a new page if the URL has a certain anchor link?
Since you don't mind using JS, you can listen to the onhashchange event to decide whether the specific section should show.
http://jsfiddle.net/C3kHT/
window.addEventListener("hashchange",function(){
if(location.hash=="#trap") /*show section*/
},false);
Sorry that I don't have an IE 8 at hand, so I'm not sure if the fiddle code actually work in IE 8.
To redirect if a url has a certain anchor:
var anchor = "#tag";
var url = "http://www.google.com";
if(window.location.indexOf(anchor) !== -1){
window.location = url;
}
Maybe try this. Start out with your hidden section set to display: none;, then use jQuery to unhide it based on the hash in the url.
CSS:
.hiddenDiv {
display: none;
}
jQuery:
function showDiv() {
if (window.location.hash === '#hashNecessaryToShowDiv') {
$('.hiddenDiv').css('display', 'block');
}
}
showDiv();

Linking to an area slightly above a specific part of a webpage

So I have this:
clicking here
<a name="link">goes here</a>
Simple, but the problem is that my site has a fixed position header that stays at the top of the page, so when a user clicks on the link, the place I want them to go to is hidden by the header. So I guess where I really want them to end up a certain amount of pixels above what I actually want them to see. I've tried putting the destination link above where I want them to end up, but it's a block of text so it changes with different screen sizes and therefore isn't consistent.
I'm wondering if there is any way to solve this problem, perhaps something with css.
Thanks in advance.
I realise this is over a year old, but for the benefit of anyone else who comes across it:
A slightly simpler solution is to put padding at the top of the section you are targeting with the link.
HTML:
<section id="section_name">
...Your stuff here...
</section>
CSS:
#section_name {
padding-top: 40px;
}
You could use a jQuery method so that when a link with a # is clicked, it finds the position of the element it's meant to go to and then moves to a position X number of pixels above the target.
Something like this:
$(function(){
var positionOffset = 50;
$('a[href=*"#"]').click(function(){
var targetHash = this.hash;
if(targetHash.length > 0 && targetHash == window.location.hash){
var elementPosition;
if($(targetHash).length){
elementPosition = $(targetHash).offset();
} else {
var targetAnchor = targetHash.replace("#", "");
elementPosition = $('a[name="' + targetAnchor + '"]').position();
}
$(window).scrollTop(elementPosition.top - positionOffset);
return false;
} else {
return true;
}
});
});