Нет полного решения этой проблемы, потому что вы хотите, чтобы целевой элемент оставался на месте при изменении размера документа, но если пользователь делает прокрутку на своей странице, невозможно узнать, где находится то же самое первое словопервая строка на дисплее. Поэтому здесь я просто заменяю одну и ту же цель сверху, когда пользователь изменяет размер своего документа, даже если он сделал прокрутку незадолго до этого.
нет необходимости в этой части CSS (удалить ее)
:target::before {margin: 0; content: ""; dis.....
и измените свой jQuery на:
$(document).ready(function () {
// global info for menu -> target elememt
var InfoTarget = { ID: null, tempo:300 }
$('a').click(function(evt){
InfoTarget.ID = $(this).attr('href') // possible target elm
// check if InfoTarget.ID exist on page
let nbElements = 0
try { nbElements = $(InfoTarget.ID).length }
catch(err) { nbElements = 0 }
if ( nbElements != 1 ) {
InfoTarget.ID = null // not target element found
}
else {
evt.preventDefault() // disable auto scroll to target element
$('html').animate({
scrollTop: ($(InfoTarget.ID).offset().top - $('#header').outerHeight(true))
}, InfoTarget.tempo );
}
});
$(window).resize(function (){
if (InfoTarget.ID) { // if InfoTarget.ID exist <=> InfoTarget.ID != null
$('html').animate({
scrollTop: ($(InfoTarget.ID).offset().top - $('#header').outerHeight(true))
}, InfoTarget.tempo);
}
});
});
Мой код говорит сам за себя, но вот полное объяснение:
принцип прост: функция target css активируется по щелчкупо ссылке <a href="#...">
для запуска прокрутки страницы в направлении элемента, имеющего для id = значение, содержащееся в начальном href.
, поэтому этот код перехватывает любой щелчок по ссылке на странице и сначала должен определитьявляется ли это ссылкой на якорь или нет.
Чтобы определить, является ли это ссылкой на якорь на странице, он просто проверяет, имеет ли элемент страницы это значение как ID
, (// check if InfoTarget.ID exists on page
).
Поскольку этот вид теста также может выдавать ошибку, этот тест помещается в try / catch
.
Если результат действительно является привязкой, действие щелчка отменяется (с evt.preventDefault()
), что не позволяет браузеру запускать автоматический переход к ссылке;
ссылкассылка хранится в объектной переменной (глобальной)
var InfoTarget = {ID: null, tempo: 300}
при просмотре: InfoTarget.ID = $(this).attr('href') // possible target elm
остальное просто, нужно прокрутить вниз до якоря. В зависимости от ширины страницы и предыдущих элементов браузеры непрерывно пересчитывают позицию каждого тега, присутствующего на странице, и jQuery может получить эту позицию смещения на $(element).offset().Top
, так как на вашей панели меню естьДля страницы, которая маскирует верхнюю часть страницы, вы должны вычесть ее высоту из позиции в свитке (= $ ('# header'). outerHeight (true))
a scroll = 0
приведет к перемещению к вершинеpage
a scroll = $(element).offset().top
помещает element
вверху страницы, на которую мы должны вычесть высоту #header
, полная формула составляет
scrollTop: ($ (InfoTarget.ID) .offset (). top - $ ('# header'). outerHeight (true))
эта команда помещается в jQuery.animate
длявизуально более плавное перемещение и использует значение InfoTarget.tempo
в качестве продолжительности этой анимации.
Во время изменения размера страницы и в той степени, в которой ссылка, имеющая цель, была предварительно нажата (поэтому всегда активна)затем запускается тот же тип прокрутки.
Различные используемые методы jQuery описаны в документе jQuery (например: https://api.jquery.com/outerHeight/)
Новое решение - Lundi 14 октября 2019 / 01:00 (в ночь на воскресенье / понедельник)
этот скрипт должен быть помещен после всех html-элементов тела
// scroll to target upon window.location.hash
$(window).on('hashchange', function() {
$('.TargetMark').removeClass('TargetMark')
$(window.location.hash).addClass('TargetMark')
setTimeout( scrollTop2, 220 ) // scroll to target after browser auto scrolling conflit
})
function scrollTop2() {
if ($('.TargetMark').length===1) { // if target exist
$('html').animate({
scrollTop: ($('.TargetMark').offset().top - $('#header').outerHeight(true))
}, 100);
}
}
В этой версии цельдобавлен элемент (TargetMark), позволяющий найти его при изменении размера окна
конечная часть
$(document).ready(function () {
//...
// ---------------------------> no call to scrollTop();
//...
});
$(window).resize(function () {
//...
scrollTop2();
//...
});
о конфликте toggleMenu:
function toggleMenu() {
$('.navbar-toggle').on('click', function () {
if ($("#js-menu").is(".expand")) {
$("#js-menu").toggleClass("expand");
$("#submenu").removeClass("active_sub").addClass("inactive_sub");
} else {
$("#js-menu").toggleClass("expand");
$("#submenu").removeClass("inactive_sub").addClass("active_sub");
}
resetTarget();
setTimeout( scrollTop2, 220 ) // scroll to target after browser auto scrolling conflit
});
}
я потратилМного времени уделяя вашему вопросу, я изучал разные подходы и различные автоматы, применяемые самими навигаторами, и с которыми нужно бороться, чтобы получить результат, который вы ищете. Я пришел к выводу, что проблема в первую очередь связана с архитектурой вашей страницы.
Тот факт, что меню ("#header") покрывает страницу ("#main"), является серьезным недостатком, препятствующим эффективному использованию. JS-код для вашего вопроса.
Вызов хэша привязки запускает одну или несколько прокруток страницы, изменение размера страницы также влечет за собой вычисление прокрутки, поскольку при изменении размера на экране также изменяется размерстраница. страница (уменьшение размера экрана вдвое приводит к удвоению размера страницы), то же самое происходит при изменении размера шрифта, а также при изменении размера страницы.
Всякий раз, когда изменяется размер страницы, браузер должен пересчитать много вещей, и некоторые из этих механизмов могут вызвать одну или несколько прокруток.
Здесь вы просите пересчитать позиционирование страницы в соответствии с элементом, который мы не можемуверен, что он полностью установлен, потому что этот процесс выполняется параллельно с другими процессами браузера, которые могут изменять полезные значения.
Плюс тот факт, что некоторые процессы браузера также работают для прокрутки страницы и что он может быть последнимготово!
Таким образом, тот факт, что меню и страница перекрываются, увеличивает сложность и делает невозможным решение проблемы. Измените свой макет, и 3/4 вашей проблемы будет исправлено.