JavaScript-слайд без JQuery

Я хотел бы иметь эффект, похожий на jQuery слайд, нобез используя jQuery или любую другую библиотеку. Я знаю, что это «возможно», так как все, что в jQuery, можно сделать в простом JavaScript. Просто сложнее.

Я не могу использовать jQuery, так как все должно быть написано в моем собственном коде без использования каких-либо библиотек.

Кто-нибудь делал что-то подобное или какие-либо эффекты, просто используя простой JavaScript?

 casablanca25 сент. 2010 г., 22:42
В значительной степени то, что сказал LatinSuD. Это не сложно, просто скучно изобретать велосипед. Я не понимаю, почему вы не можете использовать «любые библиотеки».
 LatinSuD25 сент. 2010 г., 22:38
Я думаю, что это можно сделать с помощью следующих комбинаций: javascript setInterval (), css height и css overflow = hidden;

Ответы на вопрос(10)

Немного повозившись сСимба ответ Я придумал это, чтобы учесть отступы и границы:

toggleSlide = function (el) {
    var el_max_height = 0;
    if (el.getAttribute('data-max-height')) {
        if (el.style.maxHeight.replace('px', '').replace('%', '') === '0') {
            el.style.maxHeight = el.getAttribute('data-max-height');
            el.style.paddingTop = el.getAttribute('data-pad-top');
            el.style.paddingBottom = el.getAttribute('data-pad-bottom');
            el.style.borderTop = el.getAttribute('data-border-top');
            el.style.borderBottom = el.getAttribute('data-border-bottom');
        } else {
            el.style.maxHeight = '0';
            el.style.paddingTop = '0';
            el.style.paddingBottom = '0';
            el.style.borderBottom = '0';
            el.style.borderTop = '0';
        }
    } else {
        el_max_height = getHeight(el) + 'px';
        el.style['transition-property'] = 'max-height, padding-top, padding-bottom, border-bottom, border-top';
        el.style['transition-duration'] = '0.5s';
        el.style['transition-timing-function'] = 'ease-in-out';
        el.style.overflowY = 'hidden';
        el.style.maxHeight = '0';
        el.setAttribute('data-max-height', el_max_height);
        el.setAttribute('data-pad-top', el.style.paddingTop);
        el.setAttribute('data-pad-bottom', el.style.paddingBottom);
        el.setAttribute('data-border-top', el.style.borderTop);
        el.setAttribute('data-border-bottom', el.style.borderBottom);
        el.style.display = 'block';
        setTimeout(function () { el.style.maxHeight = el_max_height; }, 10);
    }
}

На верхней границе немного мерцает, когда начинается расширение перехода, и я пока не знаю, как это исправить.

Я не модифицировал функцию Symba getHeight; для этого см. его ответ.

Решение Вопроса

Вот хороший маленький кусочек кода, который я написал с нуля.
Это чистооснованный на времени.

var minheight = 20;
var maxheight = 100;
var time = 1000;
var timer = null;
var toggled = false;

window.onload = function() {
    var controller = document.getElementById('slide');
    var slider = document.getElementById('slider');
    slider.style.height = minheight + 'px'; //not so imp,just for my example
    controller.onclick = function() {  
        clearInterval(timer);
        var instanceheight = parseInt(slider.style.height);  // Current height
        var init = (new Date()).getTime(); //start time
        var height = (toggled = !toggled) ? maxheight: minheight; //if toggled

        var disp = height - parseInt(slider.style.height);
        timer = setInterval(function() {
            var instance = (new Date()).getTime() - init; //animating time
            if(instance <= time ) { //0 -> time seconds
                var pos = instanceheight + Math.floor(disp * instance / time);
                slider.style.height =  pos + 'px';
            }else {
                slider.style.height = height + 'px'; //safety side ^^
                clearInterval(timer);
            }
        },1);
    };
};

Проверьте это здесь:http://jsbin.com/azewi5/5

 user37255126 сент. 2010 г., 15:09
да, я верю, что это можно сделать, добавив еще несколько строк кода.
 slebetman26 сент. 2010 г., 17:12
Кроме того, 1000 кадров в секунду - очень оптимистичная цель. Даже Quake не пытается достичь этой цели :-P
 Elliott26 сент. 2010 г., 14:57
Спасибо, возможно ли, чтобы он работал, когда div скрыт в css, а затем отображается как он скользит вниз?
 el toro18 мар. 2019 г., 15:13
В будущем я бы рекомендовал использовать интервал 17, потому что 17/1000 составляет около 1/60, а 60 кадров в секунду - это реальная цель для частоты кадров. Использование 1000 кадров в секунду - это просто трата вычислительной мощности.
 user37255126 сент. 2010 г., 15:35
@elliott попробуйте обновленную демоверсиюjsbin.com/azewi5/3 Я использую непрозрачность, чтобы изменить видимость
 Symba14 мар. 2015 г., 10:32
Использование css лучше, чем взлом js для эффекта перехода (ДА - использование setInterval или setTimeout - это взлом). Проверьте мое решение.
 slebetman26 сент. 2010 г., 17:04
Установка тайм-аута на 1 мс не рекомендуется, потому что в других операционных системах, кроме Windows, тик ядра установлен выше этого значения (я полагаю, что для Linux и BSD это значение равно 10 мс, что составляет 10 мс минимальное рекомендуемое значение). Это приведет к тому, что в других ОС анимация будет выглядеть медленнее, чем в Windows.

Поскольку мы находимся в 2014 году, почему бы не использовать CSS-переходы и просто изменить свойство высоты элемента?скрипка

CSS:

.wrapper {
    transition:height 1s ease-out;
    height:0;
    overflow:hidden;
}

HTML:

<div id="wrapper">
//content
</div>

JAVASCRIPT:

document.getElementById("wrapper").style.height = //content height +"px";
 swisswiss27 мар. 2018 г., 20:57
его 2018, и это должно быть главным ответом.caniuse.com/#feat=css-transitions
 Pegues19 нояб. 2014 г., 17:32
Я знаю, что такое грациозная деградация. Но теперь мы не обсуждаем тему OP, которая заключается в том, что пользователь хотел знать о решении JavaScript, а не о решении jQuery.
 Lis09 нояб. 2018 г., 13:16
Это решение не работает для меня, Win10 Chrome 70, если я изменяю свойство height с '0px' на 'initial'. Работает только для числовых значений: px, em, rem и т. Д. Так что это довольно бесполезно, если у вас нет начальной высоты элементов (что довольно трудно найти в чистом JS)
 Symba14 мар. 2015 г., 10:13
Одна проблема, если вы не знаете высоту содержимого (что не является нишевым вариантом использования)
 Vince Caregnato09 мар. 2015 г., 13:26
@ScriptsConnect Я не полностью согласен. Да, ОП попросил решение на javascript, но имейте в виду, что в 2010 году переходы CSS были неисследованной территорией, поскольку они не имели солидной кросс-браузерной поддержки. Это элегантное решение с минимальными JS и CSS.
 Ruben Serrate19 нояб. 2014 г., 13:25
@ScriptsConnect Существует нечто, называемое постепенной деградацией, и это прекрасный пример для этого. Пользователь все равно увидит изменение высоты, только то, что не анимировано. И это происходит только для очень небольшой части населения, которая использует IE9-.
 Yami Odymel12 авг. 2017 г., 20:27
Если вы не знаете высоту содержимого, вы можете сначала отобразить содержимое и получить его высоту (черезgetComputedStyle), затем сразу скрыть (так что пользователь не увидит), теперь у вас есть высота содержимого.
 Pegues19 нояб. 2014 г., 01:17
Совместимость с браузерами является причиной сделать это даже в 2014 году, и если люди не знают, как сделать это совместимым с браузером способом (чистый JS или jQuery), то это создает проблемы в их возможностях как разработчика веб-интерфейса. Слишком много разработчиков придерживаются подхода CSS3, который является проблемой для большой части населения в браузерах, практически не поддерживающих CSS3.

Посмотри наисточник jQuery для этого эффекта (slideDown звонкиshow).

 Symba14 мар. 2015 г., 10:40
Я посмотрел на исходный код для этого, но, войдя в Tween, я сказал себе: «Мне лучше делать это самостоятельно и учиться в процессе». Что я и сделал => где-то здесь, это мое решение этой проблемы.
 Dan Beam26 сент. 2010 г., 12:45
трусливый отказ понимать части JQuery (хотя я много раз заглядывал в источник) ->

может быть сделано в простом JavaScript. Просто сложнее.

На самом деле это не так уж сложно. Вам просто нужно освоиться сsetTimeout() (в любом случае, это хорошая идея, так как она учит вас стилю программирования для node.js). Самая простая реализация (не имеет всех функций jQuery, она оставлена ​​в качестве домашней работы для читателя):

function slideDown (element, duration, finalheight, callback) {
    var s = element.style;
    s.height = '0px';

    var y = 0;
    var framerate = 10;
    var one_second = 1000;
    var interval = one_second*duration/framerate;
    var totalframes = one_second*duration/interval;
    var heightincrement = finalheight/totalframes;
    var tween = function () {
        y += heightincrement;
        s.height = y+'px';
        if (y<finalheight) {
            setTimeout(tween,interval);
        }
    }
    tween();
}

Конечно, это не самый короткий способ написать это, и вам не нужно объявлять все эти переменные какone_second и т.д. Я просто сделал это для ясности, чтобы показать, что происходит.

Этот пример также короче и проще для понимания, чем попытка прочитать исходный код jQuery.

Кто-нибудь делал что-то подобное или какие-либо эффекты, просто используя простой JavaScript?

О да, конечно, это то, чем я занимаюсь по выходным:

http://slebetman.110mb.com/tank3.html (подсказка: юниты кликабельны)http://slebetman.110mb.com/jsgames/freakout
 Elliott26 сент. 2010 г., 19:14
@slebetman Я получил его сейчас, я просто пытаюсь установить div как скрытый при загрузке, и затем он отображается, пока он скользит вниз.
 Peter Ajtai26 сент. 2010 г., 05:32
+1 - за танковую анимацию;)
 Robert26 сент. 2010 г., 00:33
Работает для меня,jsfiddle.net/zZgrZ
 slebetman26 сент. 2010 г., 17:09
@Eliott: Можете ли вы опубликовать, что именно вы делаете, что делает это не работает для вас. Возможно на jsfiddle или даже как дополнение к вашему вопросу. Трудно отлаживать то, что мы не видим :-P
 slebetman26 сент. 2010 г., 17:07
@Avinash: Я не понимаю, что ты имеешь в виду не на основе времени. Он использует setTimeout для планирования изменений во времени. Конечно, это определение потока времени.
 user37255126 сент. 2010 г., 10:23
+1 классная игра, очень нравится. урод =)
 Elliott26 сент. 2010 г., 00:44
Ах, я вижу, у меня есть мой div скрытый с дисплеем: ни один в моем CSS. Как я мог заставить это показать, когда это скользит вниз, я попробовал display: block, но эффект не работает. Спасибо
 slebetman26 сент. 2010 г., 08:46
@ Роберт: Спасибо за jsfiddle. Я понял, что у меня была ошибка в моих вычислениях, и теперь она должна быть исправлена. Я хотел, чтобы продолжительность выражалась в секундах (она принимает значения с плавающей запятой).
 Elliott26 сент. 2010 г., 00:12
Спасибо, я попробовал это, но я не мог заставить это работать. Есть ли шанс на рабочий пример? Спасибо :)

высоты и использует css-переходы.

он установит max-height в 2 раза больше высоты окна браузера во время перехода, а затем уберет max-height после перехода.

полная демонстрация слайдов, демонстрация слайдов @https://kaizhu256.github.io/node-swagger-lite/build..alpha..travis-ci.org/app/index.html

CSS

.swggAnimateSlide {
    overflow-y: hidden;
    transition: all 500ms linear;
}
.swggAnimateSlideUp {
    border-bottom: 0 !important;
    border-top: 0 !important;
    margin-bottom: 0 !important;
    margin-top: 0 !important;
    max-height: 0 !important;
    padding-bottom: 0 !important;
    padding-top: 0 !important;
}

JS

domAnimateSlideDown = function (element) {
/*
 * this function will slideDown the dom-element
 */
    if (element.style.maxHeight || element.style.display !== 'none') {
        return;
    }
    element.classList.add('swggAnimateSlideUp');
    element.classList.add('swggAnimateSlide');
    element.style.display = '';
    setTimeout(function () {
        element.style.maxHeight = 2 * window.innerHeight + 'px';
        element.classList.remove('swggAnimateSlideUp');
    }, 50);
    setTimeout(function () {
        element.style.maxHeight = '';
        element.classList.remove('swggAnimateSlide');
    }, 500);
};


domAnimateSlideUp = function (element) {
/*
 * this function will slideUp the dom-element
 */
    if (element.style.maxHeight || element.style.display === 'none') {
        return;
    }
    element.style.maxHeight = 2 * window.innerHeight + 'px';
    element.classList.add('swggAnimateSlide');
    setTimeout(function () {
        element.classList.add('swggAnimateSlideUp');
        element.style.maxHeight = '0px';
    }, 50);
    setTimeout(function () {
        element.style.display = 'none';
        element.style.maxHeight = '';
        element.classList.remove('swggAnimateSlide');
        element.classList.remove('swggAnimateSlideUp');
    }, 500);
};

Проблема с более ранними ответами заключается в том, что вам нужно знать высоту, прежде чем начать. Много раз нет. Я построил слайд вниз, когда вы вначале строите div-элемент держателя, поместите объект, чтобы скользить вниз, установите отображение объекта, который нужно заблокировать, и получите высоту и используйте это для синдрома. Когда сторона готова, держатель снимается, а затем сдвиньте вниз. Ниже приведен пример.

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div >
            <div id="test" style="height: 150px; width: 100px; background-color: yellowgreen; display:none">block</div>
        </div>
        <div>&nbsp;</div>
        <div onclick="slideUp(document.getElementById('test'));">slide Up</div>
        <div>&nbsp;</div>
        <div onclick="slideDown(document.getElementById('test'))">slide down</div>
        <script>
            function slideDown(obj, speed) {
                var mySpeed = speed || 300;
                var intervals = mySpeed / 30; // we are using 30 ms intervals
                alert('intervals = ' + intervals);
                var holder = document.createElement('div');//
                var parent = obj.parentNode;
                holder.setAttribute('style', 'height: 0px; overflow:hidden');
                parent.insertBefore(holder, obj);
                parent.removeChild(obj);
                holder.appendChild(obj);
                obj.style.display = obj.getAttribute("data-original-display") || "";
                var height = obj.offsetHeight;
                var sepHeight = height / intervals;
                //  alert(sepHeight)
                var timer = setInterval(function() {
                    var holderHeight = holder.offsetHeight;
                    if (holderHeight + sepHeight < height) {
                        holder.style.height = (holderHeight + sepHeight) + 'px';
                    } else {
                        // clean up
                        holder.removeChild(obj);
                        parent.insertBefore(obj, holder);
                        parent.removeChild(holder);
                        clearInterval(timer);
                    }
                }, 30);
            }

            function slideUp(obj, speed) {
                var mySpeed = speed || 300;
                var intervals = mySpeed / 30; // we are using 30 ms intervals
                var height = obj.offsetHeight;
                var holder = document.createElement('div');//
                var parent = obj.parentNode;
                holder.setAttribute('style', 'height: ' + height + 'px; overflow:hidden');
                parent.insertBefore(holder, obj);
                parent.removeChild(obj);
                holder.appendChild(obj);
                var originalDisplay = (obj.style.display !== 'none') ? obj.style.display : '';
                obj.setAttribute("data-original-display", originalDisplay);
                var sepHeight = height / intervals;
                //  alert(sepHeight)
                var timer = setInterval(function() {
                    var holderHeight = holder.offsetHeight;
                    console.log(holderHeight);
                    if (holderHeight - sepHeight > 0) {
                        holder.style.height = (holderHeight - sepHeight) + 'px';
                    } else {
                        // clean up
                        obj.style.display = 'none';
                        holder.removeChild(obj);
                        parent.insertBefore(obj, holder);
                        parent.removeChild(holder);
                        clearInterval(timer);
                    }
                }
                , 30);
            }

        </script>
    </body>
</html>

В качестве улучшения решения @Ruben Serrate, в котором пропущен вариант использования для неизвестной высоты, я создал это с использованием CSS3 и javascript (без jQuery):

/**
* getHeight - for elements with display:none
 */
getHeight = function(el) {
    var el_style      = window.getComputedStyle(el),
        el_display    = el_style.display,
        el_position   = el_style.position,
        el_visibility = el_style.visibility,
        el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''),

        wanted_height = 0;


    // if its not hidden we just return normal height
    if(el_display !== 'none' && el_max_height !== '0') {
        return el.offsetHeight;
    }

    // the element is hidden so:
    // making the el block so we can meassure its height but still be hidden
    el.style.position   = 'absolute';
    el.style.visibility = 'hidden';
    el.style.display    = 'block';

    wanted_height     = el.offsetHeight;

    // reverting to the original values
    el.style.display    = el_display;
    el.style.position   = el_position;
    el.style.visibility = el_visibility;

    return wanted_height;
};


/**
* toggleSlide mimics the jQuery version of slideDown and slideUp
* all in one function comparing the max-heigth to 0
 */
toggleSlide = function(el) {
    var el_max_height = 0;

    if(el.getAttribute('data-max-height')) {
        // we've already used this before, so everything is setup
        if(el.style.maxHeight.replace('px', '').replace('%', '') === '0') {
            el.style.maxHeight = el.getAttribute('data-max-height');
        } else {
            el.style.maxHeight = '0';
        }
    } else {
        el_max_height                  = getHeight(el) + 'px';
        el.style['transition']         = 'max-height 0.5s ease-in-out';
        el.style.overflowY             = 'hidden';
        el.style.maxHeight             = '0';
        el.setAttribute('data-max-height', el_max_height);
        el.style.display               = 'block';

        // we use setTimeout to modify maxHeight later than display (to we have the transition effect)
        setTimeout(function() {
            el.style.maxHeight = el_max_height;
        }, 10);
    }
}

Вот демо:http://jsfiddle.net/pgfk2mvo/

Пожалуйста, дайте мне знать, если вы можете найти какие-либо улучшения в этом, так как я всегда стараюсь улучшить свой код. Удачного кодирования! : D

 lowtechsun17 янв. 2017 г., 11:25
@StevenWade Что вы имеете в видучто-то начинает открываться? Что-то мешает анимации? В каком случае? Сделать редактирование в JSFiddle возможно?
 lowtechsun17 янв. 2017 г., 11:27
@ Симба, пока отлично работает!
 swade27 июл. 2016 г., 04:51
прекрасно работает, но есть проблемы, когда что-то начинает открываться.
 reika11 июн. 2018 г., 12:53
Это «переключение» будет иметь визуальную ошибку, если div, который нужно сдвинуть вниз, виден изначально.

Вот решение использовать slideDown, slideUp анимацию снеизвестная высота содержимого элемент.https://jsfiddle.net/gebpjo1L/18/

Он основан на анимации высоты CSS 3, но для анимации требуется указанная высота содержимого, поэтому вам необходимо получить высоту содержимого с помощью JavaScript, прежде чем расширять его.

var container = document.querySelector('div')
var button    = document.querySelector('button')

button.addEventListener('click', () => {
    /** Slide down. */
    if(!container.classList.contains('active')) {
        /** Show the container. */
    	container.classList.add('active')
        container.style.height = "auto"
        
        /** Get the computed height of the container. */
    	var height = container.clientHeight + "px"

        /** Set the height of the content as 0px, */
        /** so we can trigger the slide down animation. */
        container.style.height = "0px"

        /** Do this after the 0px has applied. */
        /** It's like a delay or something. MAGIC! */
        setTimeout(() => {
            container.style.height = height
        }, 0) 
    
	/** Slide up. */
    } else {
    	/** Set the height as 0px to trigger the slide up animation. */
    	container.style.height = "0px"
        
        /** Remove the `active` class when the animation ends. */
    	container.addEventListener('transitionend', () => {
        	container.classList.remove('active')
        }, {once: true})
    }
})
div {
    transition: height .5s ease;
    overflow  : hidden;
}

div:not(.active) {
    display: none;
}
<div>
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
    I'm an unknown content height element. 
</div>
<button>Slide Toggle</button>

 Iftah13 нояб. 2017 г., 15:02
Любая причина использоватьwindow.getComputedStyle(container, null).getPropertyValue("height")  вместоcontainer.clientHeight ?
 Ciprian24 мая 2018 г., 11:29
Это лучшее решение, которое я нашел до сих пор. Маленький и лаконичный, с использованием CSS переходов.
 Yami Odymel13 нояб. 2017 г., 17:00
Я не зналcontainer.clientHeight существует. Я думаю, что они оба делают то же самое, ноcontainer.clientHeight быстрее, поэтому я отредактировал ответ, спасибо.

Я потратил много времени, чтобы разработать эти функции и сделать их максимально похожими на функции JQuery, я думаю, что это некоторые детали, которые нужно оптимизировать в функции morph, в основном по длине.

function morph( element, options, animationTime, callback ) { 
// options is an array with the same structural of Properties and DiffValues and which contains the properties values we want the animation make
	var ComputedElementStyle = window.getComputedStyle(element,null);
	var AttrElementStyle = element.style;
	var Properties = { // the actuals computed properties
		width: 		parseInt( ComputedElementStyle.getPropertyValue("width")),
		height: 	parseInt( ComputedElementStyle.getPropertyValue("height")),
		padding: {
			top: 	parseInt(ComputedElementStyle.getPropertyValue("padding-top")),
			right: 	parseInt(ComputedElementStyle.getPropertyValue("padding-right")),
			bot: 	parseInt(ComputedElementStyle.getPropertyValue("padding-bottom")),
			left:	parseInt(ComputedElementStyle.getPropertyValue("padding-left"))
			},
		margin:{
			top: 	parseInt(ComputedElementStyle.getPropertyValue("margin-top")),
			right: 	parseInt(ComputedElementStyle.getPropertyValue("margin-right")),
			bot: 	parseInt(ComputedElementStyle.getPropertyValue("margin-bottom")),
			left:	parseInt(ComputedElementStyle.getPropertyValue("margin-left"))
			} 
	};
	var DiffValues = { // the differences between actual properties values and values we want to
		width:		(options['width']!=null) ? (options['width'] - Properties['width']) : 0,
		height:		(options['height']!=null) ? (options['height'] - Properties['height']) : 0,
		padding: {
			top: 	(options['padding']&&options['padding']['top']!=null) ? options['padding']['top'] - Properties['padding']['top'] : 0,
			right: 	(options['padding']&&options['padding']['right']!=null) ? options['padding']['right'] - Properties['padding']['right'] : 0,
			bot: 	(options['padding']&&options['padding']['bot']!=null) ? options['padding']['bot'] - Properties['padding']['bot'] : 0,
			left: 	(options['padding']&&options['padding']['left']!=null) ? options['padding']['left'] - Properties['padding']['left'] : 0
			},
		margin:{
			top: 	(options['margin']&&options['margin']['top']!=null) ? options['margin']['top'] - Properties['margin']['top'] : 0,
			right: 	(options['margin']&&options['margin']['right']!=null) ? options['margin']['right'] - Properties['margin']['right'] : 0,
			bot: 	(options['margin']&&options['margin']['bot']!=null) ? options['margin']['bot'] - Properties['margin']['bot'] : 0,
			left: 	(options['margin']&&options['margin']['left']!=null) ? options['margin']['left'] - Properties['margin']['left'] : 0
			}
	};
	var beginTime = new Date().getTime(); // time at begining of animation
	animationTime = (animationTime!=null) ? animationTime : 250;
	AttrElementStyle.overflow = "hidden"; // disable the potentials scrollbars
	
	var sinceBeginTime; // time since the begining
	var progressFactor; // coeficient that correspond to the advancement of the animation
	
	timer = setInterval(function() { // begin of the animation
		sinceBeginTime = new Date().getTime() - beginTime;
		if( sinceBeginTime < animationTime ) {
			progressFactor = sinceBeginTime / animationTime;
			AttrElementStyle.width=(Properties['width'] + DiffValues['width'] * progressFactor)		+"px";
			AttrElementStyle.height=(Properties['height'] + DiffValues['height'] * progressFactor)	+"px";
			AttrElementStyle.padding=
				(Properties['padding']['top'] + DiffValues['padding']['top'] * progressFactor)		+"px "+
				(Properties['padding']['right'] + DiffValues['padding']['right'] * progressFactor)	+"px "+
				(Properties['padding']['bot'] + DiffValues['padding']['bot'] * progressFactor)		+"px "+
				(Properties['padding']['left'] + DiffValues['padding']['left'] * progressFactor)	+"px";
			AttrElementStyle.margin=
				(Properties['margin']['top'] + DiffValues['margin']['top'] * progressFactor)		+"px "+
				(Properties['margin']['right'] + DiffValues['margin']['right'] * progressFactor)	+"px "+
				(Properties['margin']['bot'] + DiffValues['margin']['bot'] * progressFactor)		+"px "+
				(Properties['margin']['left'] + DiffValues['margin']['left'] * progressFactor)		+"px";
		}else {
			AttrElementStyle.width=options['width']		+"px";
			AttrElementStyle.height=options['height']	+"px";
			AttrElementStyle.padding=
				(Properties['padding']['top'] + DiffValues['padding']['top'])		+"px "+
				(Properties['padding']['right'] + DiffValues['padding']['right'])	+"px "+
				(Properties['padding']['bot'] + DiffValues['padding']['bot'])		+"px "+
				(Properties['padding']['left'] + DiffValues['padding']['left'])		+"px";
			AttrElementStyle.margin=
				(Properties['margin']['top'] + DiffValues['margin']['top'])			+"px "+
				(Properties['margin']['right'] + DiffValues['margin']['right'])		+"px "+
				(Properties['margin']['bot'] + DiffValues['margin']['bot'])			+"px "+
				(Properties['margin']['left'] + DiffValues['margin']['left'])		+"px";
			clearInterval( timer ); // end of the animation
			if( callback!=null ) // if there is a CALLBACK then call it
				callback(Properties);
		}
	},15);
}
function slideUp( element, animationTime , callback) {
	morph( element, {
			height:0,
			padding:{
				top:0,
				bot:0
			},
			margin:{
				top:0,
				bot:0
			} },  animationTime, function(Properties) {
			// at the end of the slideUp we display: none the element and clean the other properties from style attribute
			var AttrElementStyle = element.style;
			AttrElementStyle.width="";
			AttrElementStyle.height="";
			AttrElementStyle.padding="";
			AttrElementStyle.margin="";
			element.style.display = 'none';
			if(callback)
				callback();
	});
}

function slideDown( element, animationTime , callback) {
	var AttrElementStyle = element.style;
	var ComputedElementStyle = window.getComputedStyle(element,null);
	
	AttrElementStyle.display="block";
	
	var options = { // the computed properties when element is displayed
	width: 		parseInt( ComputedElementStyle.getPropertyValue("width")),
	height: 	parseInt( ComputedElementStyle.getPropertyValue("height")),
	padding: {
		top: 	parseInt(ComputedElementStyle.getPropertyValue("padding-top")),
		bot: 	parseInt(ComputedElementStyle.getPropertyValue("padding-bottom"))
		},
	margin:{
		top: 	parseInt(ComputedElementStyle.getPropertyValue("margin-top")),
		bot: 	parseInt(ComputedElementStyle.getPropertyValue("margin-bottom"))
		} 
	};
	// after getting the actuals properties values of the element we flatten it
	AttrElementStyle.height="0";
	AttrElementStyle.paddingTop="0";
	AttrElementStyle.paddingBottom="0";
	AttrElementStyle.marginTop="0";
	AttrElementStyle.marginBottom="0";
	
	morph( element, options , animationTime, function() { // morph the element from flat to the options properties that are right
		// at the end of slideDown we clean up the style but keep the display: block if the element is display: none in the stylesheet
		AttrElementStyle.width="";
		AttrElementStyle.height="";
		AttrElementStyle.padding="";
		AttrElementStyle.margin="";
		element.style.display = 'block';
		if(callback) // if there is a CALLBACK then call it (we are in the morph() callback)
			callback();
	})
}
p{
  width:50%;
  height:auto;
  padding:40px 0 10px;
  margin: 10px 0 40px;
  border:2px solid red
}
div{
  border:1px solid blue;
  padding:10px
}
<div>
  <p id='p'>loiloilozoifboiygdouhbodihfgsd</br>rihgdggisbifghbsoifnsf</br>giodsbgsigfbsjgsgs</p>
</div>

<button onClick="slideUp( document.getElementById('p') ,500)">testUp</button>
<button onClick="slideDown( document.getElementById('p') ,500)">testDown</button>

<button id='btn1' onClick="morph( document.getElementById('btn1'),{ width: 120,height:130,padding:{top:70,left:50},margin:{right:40}} ,1000)">morphIt</button>
<button onClick="document.getElementById('btn1').style=''">reset btn1</button>

Ваш ответ на вопрос